home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / occsite.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  94.1 KB  |  3,575 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include "occimpl.h"
  13. #ifndef __msdadc_h__
  14. #include "msdadc.h"
  15. #endif
  16.  
  17. #ifdef AFX_OCC_SEG
  18. #pragma code_seg(AFX_OCC_SEG)
  19. #endif
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. #define new DEBUG_NEW
  27.  
  28. #define S_QUICKACTIVATED S_FALSE
  29.  
  30. #include "initguid.h"
  31. #define DBINITCONSTANTS
  32. #define INITGUID
  33.  
  34. DEFINE_GUID(IID_IDataSourceListener,0x7C0FFAB2L,0xCD84,0x11D0,0x94,0x9A,0x00,0xA0,0xC9,0x11,0x10,0xED);
  35. DEFINE_GUID(IID_IDataSource,0x7c0ffab3L, 0xcd84, 0x11d0, 0x94, 0x9a, 0x00, 0xa0, 0xc9, 0x11, 0x10, 0xed);
  36.  
  37. /////////////////////////////////////////////////////////////////////////////
  38. // COleControlSite
  39.  
  40. BEGIN_INTERFACE_MAP(COleControlSite, CCmdTarget)
  41.     INTERFACE_PART(COleControlSite, IID_IOleClientSite, OleClientSite)
  42.     INTERFACE_PART(COleControlSite, IID_IOleInPlaceSite, OleIPSite)
  43.     INTERFACE_PART(COleControlSite, IID_IOleControlSite, OleControlSite)
  44.     INTERFACE_PART(COleControlSite, IID_IDispatch, AmbientProps)
  45. #if !defined(_WIN32_WCE)
  46.     INTERFACE_PART(COleControlSite, IID_IBoundObjectSite, BoundObjectSite)
  47.     INTERFACE_PART(COleControlSite, IID_INotifyDBEvents, NotifyDBEvents)
  48.     INTERFACE_PART(COleControlSite, IID_IRowsetNotify, RowsetNotify)
  49. #endif // _WIN32_WCE
  50. END_INTERFACE_MAP()
  51.  
  52. COleControlSite::COleControlSite(COleControlContainer* pCtrlCont) :
  53.     m_pCtrlCont(pCtrlCont),
  54.     m_pWndCtrl(NULL),
  55.     m_nID((UINT)-1),
  56.     m_pObject(NULL),
  57.     m_pInPlaceObject(NULL),
  58.     m_pActiveObject(NULL),
  59.     m_dwEventSink(0),
  60.     m_dwPropNotifySink(0),
  61. #if defined(_WIN32_WCE)
  62.     m_dwMiscStatus(0)
  63. #else // _WIN32_WCE
  64.     m_dwMiscStatus(0),
  65.     m_dwNotifyDBEvents(0),
  66.     m_pDataSourceControl(NULL),
  67.     m_pDSCSite(NULL),
  68.     m_defdispid(0),
  69.     m_dwType(0),
  70.     m_pBindings(NULL),
  71.     m_bIgnoreNotify(FALSE),
  72.     m_bIsDirty(FALSE)
  73. #endif // _WIN32_WCE
  74. {
  75.     memset(&m_varResult, 0, sizeof(VARIANT));
  76.     m_varResult.vt = VT_EMPTY;
  77. }
  78.  
  79. COleControlSite::~COleControlSite()
  80. {
  81. #if !defined(_WIN32_WCE)
  82.     if (m_pDataSourceControl)
  83.         delete m_pDataSourceControl;
  84. #endif // _WIN32_WCE
  85.  
  86.     DetachWindow();
  87.  
  88.     DisconnectSink(m_iidEvents, m_dwEventSink);
  89.     DisconnectSink(IID_IPropertyNotifySink, m_dwPropNotifySink);
  90. #if !defined(_WIN32_WCE)
  91.     DisconnectSink(IID_INotifyDBEvents, m_dwNotifyDBEvents);
  92. #endif // _WIN32_WCE
  93.  
  94.     if (m_pInPlaceObject != NULL)
  95.     {
  96.         m_pInPlaceObject->InPlaceDeactivate();
  97.         m_pInPlaceObject->Release();
  98.         m_pInPlaceObject = NULL;
  99.     }
  100.  
  101.     if (m_pActiveObject != NULL)
  102.     {
  103.         m_pActiveObject->Release();
  104.         m_pActiveObject = NULL;
  105.     }
  106.  
  107.     if (m_pObject != NULL)
  108.     {
  109.         m_pObject->SetClientSite(NULL);
  110.         m_pObject->Close(OLECLOSE_NOSAVE);
  111.         m_pObject->Release();
  112.         m_pObject = NULL;
  113.     }
  114.  
  115.     ::VariantClear(&m_varResult);
  116.  
  117. #if !defined(_WIN32_WCE)
  118.     BindProperty(DISPID_UNKNOWN, NULL);
  119. #endif // _WIN32_WCE
  120. }
  121.  
  122. BOOL COleControlSite::SetExtent()
  123. {
  124.     CSize size(m_rect.Size());
  125.     CClientDC dc(NULL);
  126.     dc.DPtoHIMETRIC(&size);
  127.  
  128.     HRESULT hr;
  129.  
  130.     if (SUCCEEDED(hr = m_pObject->SetExtent(DVASPECT_CONTENT, (SIZEL*)&size)))
  131.     {
  132.         if (SUCCEEDED(m_pObject->GetExtent(DVASPECT_CONTENT, (SIZEL*)&size)))
  133.         {
  134.             dc.HIMETRICtoDP(&size);
  135.             m_rect.right = m_rect.left + size.cx;
  136.             m_rect.bottom = m_rect.top + size.cy;
  137.         }
  138.     }
  139.  
  140.     return SUCCEEDED(hr);
  141. }
  142.  
  143. HRESULT COleControlSite::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
  144.     LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, UINT nID,
  145.     CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
  146. {
  147.    CRect rect2( rect );
  148.    CPoint pt;
  149.    CSize size;
  150.  
  151.    pt = rect2.TopLeft();
  152.    size = rect2.Size();
  153.  
  154.    return( CreateControl( pWndCtrl, clsid, lpszWindowName, dwStyle, &pt, &size,
  155.       nID, pPersist, bStorage, bstrLicKey ) );
  156. }
  157.  
  158. HRESULT COleControlSite::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
  159.     LPCTSTR lpszWindowName, DWORD dwStyle, const POINT* ppt, const SIZE* psize,
  160.    UINT nID, CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
  161. {
  162.     HRESULT hr = E_FAIL;
  163.     m_hWnd = NULL;
  164.    CSize size;
  165.  
  166.     // Connect the OLE Control with its proxy CWnd object
  167.     if (pWndCtrl != NULL)
  168.     {
  169.         ASSERT(pWndCtrl->m_pCtrlSite == NULL);
  170.         m_pWndCtrl = pWndCtrl;
  171.         pWndCtrl->m_pCtrlSite = this;
  172.     }
  173.  
  174.     // Initialize OLE, if necessary
  175.     _AFX_THREAD_STATE* pState = AfxGetThreadState();
  176.     if (!pState->m_bNeedTerm && !AfxOleInit())
  177.         return hr;
  178.  
  179.     if (SUCCEEDED(hr = CreateOrLoad(clsid, pPersist, bStorage, bstrLicKey)))
  180.     {
  181.         ASSERT(m_pObject != NULL);
  182.         m_nID = nID;
  183.  
  184.         if (psize == NULL)
  185.         {
  186.             // If psize is NULL, ask the object how big it wants to be.
  187.             CClientDC dc(NULL);
  188.  
  189.             m_pObject->GetExtent(DVASPECT_CONTENT, &size);
  190.             dc.HIMETRICtoDP(&size);
  191.             m_rect = CRect(*ppt, size);
  192.         }
  193.         else
  194.         {
  195.             m_rect = CRect(*ppt, *psize);
  196.         }
  197.  
  198.         m_dwStyleMask = WS_GROUP | WS_TABSTOP;
  199.  
  200.         if (m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON)
  201.             m_dwStyleMask |= BS_DEFPUSHBUTTON;
  202.  
  203.         if (m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
  204.             dwStyle &= ~WS_VISIBLE;
  205.  
  206.         m_dwStyle = dwStyle & m_dwStyleMask;
  207.  
  208.         // If control wasn't quick-activated, then connect sinks now.
  209.         if (hr != S_QUICKACTIVATED)
  210.         {
  211.             m_dwEventSink = ConnectSink(m_iidEvents, &m_xEventSink);
  212.             m_dwPropNotifySink = ConnectSink(IID_IPropertyNotifySink,
  213.                 &m_xPropertyNotifySink);
  214.         }
  215. #if !defined(_WIN32_WCE)
  216.         m_dwNotifyDBEvents = ConnectSink(IID_INotifyDBEvents, &m_xNotifyDBEvents);
  217. #endif // _WIN32_WCE
  218.  
  219.         // Now that the object has been created, attempt to
  220.         // in-place activate it.
  221.  
  222.         SetExtent();
  223.  
  224.         if (SUCCEEDED(hr = m_pObject->QueryInterface(IID_IOleInPlaceObject,
  225.                 (LPVOID*)&m_pInPlaceObject)))
  226.         {
  227.             if (dwStyle & WS_VISIBLE)
  228.             {
  229.                 // control is visible: just activate it
  230.                 hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
  231.             }
  232.             else
  233.             {
  234.                 // control is not visible: activate off-screen, hide, then move
  235.                 m_rect.OffsetRect(-32000, -32000);
  236.                 if (SUCCEEDED(hr = DoVerb(OLEIVERB_INPLACEACTIVATE)) &&
  237.                     SUCCEEDED(hr = DoVerb(OLEIVERB_HIDE)))
  238.                 {
  239.                     m_rect.OffsetRect(32000, 32000);
  240.                     hr = m_pInPlaceObject->SetObjectRects(m_rect, m_rect);
  241.                 }
  242.             }
  243.         }
  244.         else
  245.         {
  246.             TRACE1("IOleInPlaceObject not supported on OLE control (dialog ID %d).\n", nID);
  247.             TRACE1(">>> Result code: 0x%08lx\n", hr);
  248.         }
  249.  
  250.         if (SUCCEEDED(hr))
  251.             GetControlInfo();
  252.  
  253.         // if QueryInterface or activation failed, cleanup everything
  254.         if (FAILED(hr))
  255.         {
  256.             if (m_pInPlaceObject != NULL)
  257.             {
  258.                 m_pInPlaceObject->Release();
  259.                 m_pInPlaceObject = NULL;
  260.             }
  261.             DisconnectSink(m_iidEvents, m_dwEventSink);
  262.             DisconnectSink(IID_IPropertyNotifySink, m_dwPropNotifySink);
  263. #if defined(_WIN32_WCE)
  264.             m_dwEventSink = 0;
  265. #else // _WIN32_WCE
  266.             DisconnectSink(IID_INotifyDBEvents, m_dwNotifyDBEvents);
  267.             m_dwEventSink = 0;
  268.             m_dwPropNotifySink = 0;
  269.             m_dwNotifyDBEvents = 0;
  270. #endif // _WIN32_WCE
  271.             m_pObject->Release();
  272.             m_pObject = NULL;
  273.         }
  274.     }
  275.  
  276.     if (SUCCEEDED(hr))
  277.     {
  278.         AttachWindow();
  279.  
  280.         ASSERT(m_hWnd != NULL);
  281.  
  282.         // Initialize the control's Caption or Text property, if any
  283.         if (lpszWindowName != NULL)
  284.             SetWindowText(lpszWindowName);
  285.  
  286.         // Initialize styles
  287.         ModifyStyle(0, m_dwStyle | (dwStyle & (WS_DISABLED|WS_BORDER)), 0);
  288.     }
  289.  
  290.     return hr;
  291. }
  292.  
  293. BOOL COleControlSite::DestroyControl()
  294. {
  295.     ASSERT(m_hWnd != NULL);     // was control ever successfully created?
  296.     m_pCtrlCont->m_siteMap.RemoveKey(m_hWnd);
  297.  
  298.     //VBBUG: VB controls will crash if IOleObject::Close is called on them
  299.     //    when they have focus (and unfortunately, deactivating them does not
  300.     //    always move the focus).  To work around this problem, we always hide
  301.     //    the control before closing it.
  302.     ShowWindow(SW_HIDE);
  303.  
  304.     // Now it is safe to close the control.
  305.     delete this;
  306.  
  307.     return TRUE;
  308. }
  309.  
  310. AFX_STATIC HRESULT AFXAPI _AfxCoCreateInstanceLic(REFCLSID clsid, LPUNKNOWN pUnkOuter,
  311.     DWORD dwClsCtx, REFIID iid, LPVOID* ppv, BSTR bstrLicKey)
  312. {
  313.     HRESULT hr;
  314.  
  315.     if (bstrLicKey == NULL)
  316.     {
  317.         LPCLASSFACTORY pClassFactory = NULL;
  318.  
  319.         if (SUCCEEDED(hr = CoGetClassObject(clsid, dwClsCtx, NULL,
  320.             IID_IClassFactory, (void**)&pClassFactory)))
  321.         {
  322.             ASSERT(pClassFactory != NULL);
  323.             hr = pClassFactory->CreateInstance(pUnkOuter, iid, ppv);
  324.             pClassFactory->Release();
  325.         }
  326.     }
  327.     else
  328.     {
  329.         LPCLASSFACTORY2 pClassFactory = NULL;
  330.  
  331.         if (SUCCEEDED(hr = CoGetClassObject(clsid, dwClsCtx, NULL,
  332.             IID_IClassFactory2, (void**)&pClassFactory)))
  333.         {
  334.             ASSERT(pClassFactory != NULL);
  335.             hr = pClassFactory->CreateInstanceLic(pUnkOuter, NULL, iid,
  336.                 bstrLicKey, ppv);
  337.             pClassFactory->Release();
  338.         }
  339.     }
  340.  
  341.     return hr;
  342. }
  343.  
  344. AFX_STATIC_DATA const struct { DISPID dwDispID; DWORD dwFlag; } _afxAmbients[] =
  345. {
  346.     { DISPID_AMBIENT_USERMODE,          QACONTAINER_USERMODE },
  347.     { DISPID_AMBIENT_UIDEAD,            QACONTAINER_UIDEAD },
  348.     { DISPID_AMBIENT_SHOWGRABHANDLES,   QACONTAINER_SHOWGRABHANDLES },
  349.     { DISPID_AMBIENT_SHOWHATCHING,      QACONTAINER_SHOWHATCHING },
  350.     { DISPID_AMBIENT_DISPLAYASDEFAULT,  QACONTAINER_DISPLAYASDEFAULT },
  351.     { DISPID_AMBIENT_AUTOCLIP,          QACONTAINER_AUTOCLIP },
  352.     { DISPID_AMBIENT_MESSAGEREFLECT,    QACONTAINER_MESSAGEREFLECT },
  353.     { DISPID_AMBIENT_SUPPORTSMNEMONICS, QACONTAINER_SUPPORTSMNEMONICS },
  354. };
  355.  
  356. BOOL COleControlSite::QuickActivate()
  357. {
  358.     BOOL bQuickActivated = FALSE;
  359.     IQuickActivate* pQuick = NULL;
  360.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IQuickActivate,
  361.         reinterpret_cast<void**>(&pQuick))))
  362.     {
  363.         ASSERT(pQuick != NULL);
  364.  
  365.         // Initialize QACONTAINER structure.
  366.         QACONTAINER qaContainer;
  367.         qaContainer.cbSize = sizeof(QACONTAINER);
  368.         qaContainer.pClientSite = &m_xOleClientSite;
  369.         qaContainer.pAdviseSink = NULL;
  370.         qaContainer.pPropertyNotifySink = &m_xPropertyNotifySink;
  371.         qaContainer.pUnkEventSink = &m_xEventSink;
  372.         qaContainer.pUndoMgr = NULL;
  373.         qaContainer.hpal = NULL;
  374.         qaContainer.pBindHost = NULL;
  375.  
  376.         // Fill ambient property values in QACONTAINER.
  377.         COleVariant var;
  378.         CWnd* pWndContain = m_pCtrlCont->m_pWnd;
  379.  
  380.         qaContainer.dwAmbientFlags = 0;
  381.         for (int i = 0; i < _countof(_afxAmbients); i++)
  382.         {
  383.             pWndContain->OnAmbientProperty(this, _afxAmbients[i].dwDispID, &var);
  384.             if (V_BOOL(&var))
  385.                 qaContainer.dwAmbientFlags |= _afxAmbients[i].dwFlag;
  386.         }
  387.  
  388.         pWndContain->OnAmbientProperty(this, DISPID_AMBIENT_FORECOLOR, &var);
  389.         qaContainer.colorFore = V_I4(&var);
  390.         pWndContain->OnAmbientProperty(this, DISPID_AMBIENT_BACKCOLOR, &var);
  391.         qaContainer.colorBack = V_I4(&var);
  392.         pWndContain->OnAmbientProperty(this, DISPID_AMBIENT_APPEARANCE, &var);
  393.         qaContainer.dwAppearance = V_I2(&var);
  394.         pWndContain->OnAmbientProperty(this, DISPID_AMBIENT_LOCALEID, &var);
  395.         qaContainer.lcid = V_I4(&var);
  396.         pWndContain->OnAmbientProperty(this, DISPID_AMBIENT_FONT, &var);
  397.         if (FAILED(V_DISPATCH(&var)->QueryInterface(IID_IFont,
  398.             reinterpret_cast<void**>(&qaContainer.pFont))))
  399.         {
  400.             qaContainer.pFont = NULL;
  401.         }
  402.  
  403.         // Initialize QACONTROL structure.
  404.         QACONTROL qaControl;
  405.         qaControl.cbSize = sizeof(QACONTROL);
  406.  
  407.         // Do the quick activation.
  408.         if (SUCCEEDED(pQuick->QuickActivate(&qaContainer, &qaControl)))
  409.         {
  410.             // Extract return values from QACONTROL structure.
  411.             m_dwMiscStatus = qaControl.dwMiscStatus;
  412.             m_dwEventSink = qaControl.dwEventCookie;
  413.             m_dwPropNotifySink = qaControl.dwPropNotifyCookie;
  414.             bQuickActivated = TRUE;
  415.         }
  416.         pQuick->Release();
  417.  
  418.         if (qaContainer.pFont != NULL)
  419.             qaContainer.pFont->Release();
  420.     }
  421.  
  422.     return bQuickActivated;
  423. }
  424.  
  425. HRESULT COleControlSite::CreateOrLoad(REFCLSID clsid, CFile* pFile,
  426.     BOOL bStorage, BSTR bstrLicKey)
  427. {
  428.     ASSERT(m_pObject == NULL);
  429.  
  430. #ifdef _DEBUG
  431.     OLECHAR wszClsid[40];
  432.     StringFromGUID2(clsid, wszClsid, 40);
  433. #endif //_DEBUG
  434.  
  435.     HRESULT hr;
  436.     if (FAILED(hr = _AfxCoCreateInstanceLic(clsid, NULL,
  437.         CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, IID_IOleObject,
  438.         (void**)&m_pObject, bstrLicKey)))
  439.     {
  440.         TRACE1("CoCreateInstance of OLE control %ls failed.\n", wszClsid);
  441.         TRACE1(">>> Result code: 0x%08lx\n", hr);
  442.         TRACE0(">>> Is the control is properly registered?\n");
  443.         return hr;
  444.     }
  445.  
  446.     LPPERSISTSTREAMINIT pPersStm = NULL;
  447.     LPPERSISTSTORAGE pPersStg = NULL;
  448.     LPPERSISTMEMORY pPersMem = NULL;
  449.  
  450.     GetEventIID(&m_iidEvents);
  451.     // Try to quick-activate first
  452.     BOOL bQuickActivated = QuickActivate();
  453.  
  454.     if (!bQuickActivated)
  455.     {
  456.         m_pObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
  457.  
  458.         // set client site first, if appropriate
  459.         if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
  460.         {
  461.             if (FAILED(hr = m_pObject->SetClientSite(&m_xOleClientSite)))
  462.             {
  463.                 TRACE1("SetClientSite on OLE control %ls failed.\n", wszClsid);
  464.                 TRACE1(">>> Result code: 0x%08lx\n", hr);
  465.                 goto CreateOrLoadFailed;
  466.             }
  467.         }
  468.     }
  469.  
  470.     ASSERT(!bStorage || pFile != NULL);
  471.  
  472.     // initialize via IPersistMemory (direct buffering)
  473.     if (pFile != NULL && !bStorage &&
  474.         SUCCEEDED(m_pObject->QueryInterface(IID_IPersistMemory, (void**)&pPersMem)) &&
  475.         pFile->GetBufferPtr(CFile::bufferCheck) != 0)
  476.     {
  477.         ASSERT(pPersMem != NULL);
  478.  
  479.         // file supports direct buffering, get its buffer pointer and size
  480.         LPVOID pvBuffer = NULL;
  481.         LPVOID pvEnd;
  482.         ULONG cbBuffer = pFile->GetBufferPtr(
  483.             CFile::bufferRead, (UINT)-1, &pvBuffer, &pvEnd);
  484.         ASSERT(((LPBYTE)pvEnd - (LPBYTE)pvBuffer) == (int)cbBuffer);
  485.  
  486.         // and then load it directly
  487.         hr = pPersMem->Load(pvBuffer, cbBuffer);
  488.         pPersMem->Release();
  489.         pPersMem = NULL;
  490.         if (FAILED(hr))
  491.             goto CreateOrLoadFailed;
  492.     }
  493.     // initialize via IPersistStreamInit
  494.     else if (!bStorage && SUCCEEDED(m_pObject->QueryInterface(
  495.         IID_IPersistStreamInit, (void**)&pPersStm)))
  496.     {
  497.         ASSERT(pPersStm != NULL);
  498.  
  499.         if (pFile == NULL)
  500.         {
  501.             // just call InitNew
  502.             hr = pPersStm->InitNew();
  503.         }
  504.         else
  505.         {
  506.             // open an IStream on the data and pass it to Load
  507.             CArchive ar(pFile, CArchive::load);
  508.             CArchiveStream stm(&ar);
  509.             hr = pPersStm->Load(&stm);
  510.         }
  511.         pPersStm->Release();
  512.  
  513.         if (FAILED(hr))
  514.         {
  515.             TRACE1("InitNew or Load on OLE control %ls failed.\n", wszClsid);
  516.             TRACE1(">>> Result code: 0x%08lx\n", hr);
  517.             goto CreateOrLoadFailed;
  518.         }
  519.     }
  520. #if !defined(_WIN32_WCE) 
  521. // WinCE: not enough OS support to support IStorage persistance on the container side 
  522.     else if (SUCCEEDED(m_pObject->QueryInterface(
  523.         IID_IPersistStorage, (void**)&pPersStg)))
  524.     {
  525.         ASSERT(pPersStg != NULL);
  526.  
  527.         if (pFile == NULL)
  528.         {
  529.             LPSTORAGE pStorage = NULL;
  530.             if (SUCCEEDED(hr = StgCreateDocfile(NULL,
  531.                     STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0,
  532.                     &pStorage)))
  533.                 {
  534.                     ASSERT(pStorage != NULL);
  535.                     hr = pPersStg->InitNew(pStorage);
  536.                     pStorage->Release();
  537.                 }
  538.             // create a scratch IStorage and pass it to InitNew
  539.             LPLOCKBYTES pLockBytes = NULL;
  540.             if (SUCCEEDED(hr = CreateILockBytesOnHGlobal(NULL, TRUE,
  541.                 &pLockBytes)))
  542.             {
  543.                 ASSERT(pLockBytes != NULL);
  544.                 LPSTORAGE pStorage = NULL;
  545.                 if (SUCCEEDED(hr = StgCreateDocfileOnILockBytes(pLockBytes,
  546.                     STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0,
  547.                     &pStorage)))
  548.                 {
  549.                     ASSERT(pStorage != NULL);
  550.                     hr = pPersStg->InitNew(pStorage);
  551.                     pStorage->Release();
  552.                 }
  553.                 pLockBytes->Release();
  554.             }
  555.         }
  556.         else if (bStorage)
  557.         {
  558.             // copy data to an HGLOBAL, so we can build an IStorage on it
  559.             UINT cb = pFile->GetLength();
  560.             HGLOBAL hGlobal;
  561.             BYTE* pbData;
  562.  
  563.             if (((hGlobal = GlobalAlloc(GMEM_FIXED, cb)) != NULL) &&
  564.                 ((pbData = (BYTE*)GlobalLock(hGlobal)) != NULL))
  565.             {
  566.                 pFile->Read(pbData, cb);
  567.                 GlobalUnlock(hGlobal);
  568.             }
  569.             else
  570.             {
  571.                 hr = E_OUTOFMEMORY;
  572.                 hGlobal = NULL;
  573.             }
  574.  
  575.             // open an IStorage on the data and pass it to Load
  576.             LPLOCKBYTES pLockBytes = NULL;
  577.             if ((hGlobal != NULL) &&
  578.                 SUCCEEDED(hr = CreateILockBytesOnHGlobal(hGlobal, TRUE,
  579.                 &pLockBytes)))
  580.             {
  581.                 ASSERT(pLockBytes != NULL);
  582.                 LPSTORAGE pStorage = NULL;
  583.                 if (SUCCEEDED(hr = StgOpenStorageOnILockBytes(pLockBytes, NULL,
  584.                     STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage)))
  585.                 {
  586.                     ASSERT(pStorage != NULL);
  587.                     hr = pPersStg->Load(pStorage);
  588.                     pStorage->Release();
  589.                 }
  590.                 pLockBytes->Release();
  591.             }
  592.         }
  593.         else
  594.         {
  595.             hr = E_UNEXPECTED;
  596.         }
  597.         pPersStg->Release();
  598.  
  599.         if (FAILED(hr))
  600.         {
  601.             TRACE1("InitNew or Load on OLE control %ls failed.\n", wszClsid);
  602.             TRACE1(">>> Result code: 0x%08lx\n", hr);
  603.             goto CreateOrLoadFailed;
  604.         }
  605.     }
  606. #endif // _WIN32_WCE
  607.     else
  608.     {
  609.         TRACE1("Persistence not supported on OLE control %ls.\n", wszClsid);
  610.         TRACE1(">>> Result code: 0x%08lx\n", hr);
  611.         goto CreateOrLoadFailed;
  612.     }
  613.  
  614.     if (!bQuickActivated)
  615.     {
  616.         // set client site last, if appropriate
  617.         if (!(m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
  618.         {
  619.             if (FAILED(hr = m_pObject->SetClientSite(&m_xOleClientSite)))
  620.             {
  621.                 TRACE1("SetClientSite on OLE control %ls failed.\n", wszClsid);
  622.                 TRACE1(">>> Result code: 0x%08lx\n", hr);
  623.                 goto CreateOrLoadFailed;
  624.             }
  625.         }
  626.     }
  627.  
  628. CreateOrLoadFailed:
  629.     if (FAILED(hr) && (m_pObject != NULL))
  630.     {
  631.         m_pObject->Close(OLECLOSE_NOSAVE);
  632.         m_pObject->Release();
  633.         m_pObject = NULL;
  634.     }
  635.  
  636.     if (pPersMem != NULL)
  637.         pPersMem->Release();
  638.  
  639.     if (bQuickActivated && SUCCEEDED(hr))
  640.         hr = S_QUICKACTIVATED;
  641.  
  642.     return hr;
  643. }
  644.  
  645. UINT COleControlSite::GetID()
  646. {
  647.     return m_nID;
  648. }
  649.  
  650. HRESULT COleControlSite::DoVerb(LONG nVerb, LPMSG lpMsg)
  651. {
  652.     return m_pObject->DoVerb(nVerb, lpMsg, &m_xOleClientSite, 0,
  653.         m_pCtrlCont->m_pWnd->m_hWnd, m_rect);
  654. }
  655.  
  656. BOOL COleControlSite::IsDefaultButton()
  657. {
  658.     return ((m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON) &&
  659.         (m_dwStyle & BS_DEFPUSHBUTTON));
  660. }
  661.  
  662. DWORD COleControlSite::GetDefBtnCode()
  663. {
  664.     if (m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON)
  665.         return (m_dwStyle & BS_DEFPUSHBUTTON) ?
  666.             DLGC_DEFPUSHBUTTON :
  667.             DLGC_UNDEFPUSHBUTTON;
  668.     else
  669.         return 0;
  670. }
  671.  
  672. void COleControlSite::SetDefaultButton(BOOL bDefault)
  673. {
  674.     if (!(m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON))
  675.         return;
  676.  
  677.     if (((m_dwStyle & BS_DEFPUSHBUTTON) != 0) == bDefault)
  678.         return;
  679.  
  680.     m_dwStyle ^= BS_DEFPUSHBUTTON;
  681.  
  682.     // Notify control that its "defaultness" has changed.
  683.     LPOLECONTROL pOleCtl = NULL;
  684.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IOleControl,
  685.         (LPVOID*)&pOleCtl)))
  686.     {
  687.         ASSERT(pOleCtl != NULL);
  688.         pOleCtl->OnAmbientPropertyChange(DISPID_AMBIENT_DISPLAYASDEFAULT);
  689.         pOleCtl->Release();
  690.     }
  691. }
  692.  
  693. DWORD COleControlSite::ConnectSink(REFIID iid, LPUNKNOWN punkSink)
  694. {
  695.     ASSERT(m_pObject != NULL);
  696.  
  697.     LPCONNECTIONPOINTCONTAINER pConnPtCont;
  698.  
  699.     if ((m_pObject != NULL) &&
  700.         SUCCEEDED(m_pObject->QueryInterface(IID_IConnectionPointContainer,
  701.             (LPVOID*)&pConnPtCont)))
  702.     {
  703.         ASSERT(pConnPtCont != NULL);
  704.         LPCONNECTIONPOINT pConnPt = NULL;
  705.         DWORD dwCookie = 0;
  706.  
  707.         if (SUCCEEDED(pConnPtCont->FindConnectionPoint(iid, &pConnPt)))
  708.         {
  709.             ASSERT(pConnPt != NULL);
  710.             pConnPt->Advise(punkSink, &dwCookie);
  711.             pConnPt->Release();
  712.         }
  713.  
  714.         pConnPtCont->Release();
  715.         return dwCookie;
  716.     }
  717.  
  718.     return 0;
  719. }
  720.  
  721. void COleControlSite::DisconnectSink(REFIID iid, DWORD dwCookie)
  722. {
  723.     if (dwCookie == 0 || m_pObject == NULL)
  724.         return;
  725.  
  726.     LPCONNECTIONPOINTCONTAINER pConnPtCont;
  727.  
  728.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IConnectionPointContainer,
  729.             (LPVOID*)&pConnPtCont)))
  730.     {
  731.         ASSERT(pConnPtCont != NULL);
  732.         LPCONNECTIONPOINT pConnPt = NULL;
  733.  
  734.         if (SUCCEEDED(pConnPtCont->FindConnectionPoint(iid, &pConnPt)))
  735.         {
  736.             ASSERT(pConnPt != NULL);
  737.             pConnPt->Unadvise(dwCookie);
  738.             pConnPt->Release();
  739.         }
  740.  
  741.         pConnPtCont->Release();
  742.     }
  743. }
  744.  
  745. #define IMPLTYPE_MASK \
  746.     (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE | IMPLTYPEFLAG_FRESTRICTED)
  747.  
  748. #define IMPLTYPE_DEFAULTSOURCE \
  749.     (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE)
  750.  
  751. BOOL COleControlSite::GetEventIID(IID* piid)
  752. {
  753.     *piid = GUID_NULL;
  754.  
  755.     ASSERT(m_pObject != NULL);
  756.  
  757.     // Use IProvideClassInfo2, if control supports it.
  758.     LPPROVIDECLASSINFO2 pPCI2 = NULL;
  759.  
  760.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IProvideClassInfo2,
  761.         (LPVOID*)&pPCI2)))
  762.     {
  763.         ASSERT(pPCI2 != NULL);
  764.  
  765.         if (SUCCEEDED(pPCI2->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid)))
  766.             ASSERT(!IsEqualIID(*piid, GUID_NULL));
  767.         else
  768.             ASSERT(IsEqualIID(*piid, GUID_NULL));
  769.  
  770.         pPCI2->Release();
  771.     }
  772.  
  773.     // Fall back on IProvideClassInfo, if IProvideClassInfo2 not supported.
  774.     LPPROVIDECLASSINFO pPCI = NULL;
  775.  
  776.     if (IsEqualIID(*piid, GUID_NULL) &&
  777.         SUCCEEDED(m_pObject->QueryInterface(IID_IProvideClassInfo,
  778.         (LPVOID*)&pPCI)))
  779.     {
  780.         ASSERT(pPCI != NULL);
  781.  
  782.         LPTYPEINFO pClassInfo = NULL;
  783.  
  784.         if (SUCCEEDED(pPCI->GetClassInfo(&pClassInfo)))
  785.         {
  786.             ASSERT(pClassInfo != NULL);
  787.  
  788.             LPTYPEATTR pClassAttr;
  789.             if (SUCCEEDED(pClassInfo->GetTypeAttr(&pClassAttr)))
  790.             {
  791.                 ASSERT(pClassAttr != NULL);
  792.                 ASSERT(pClassAttr->typekind == TKIND_COCLASS);
  793.  
  794.                 // Search for typeinfo of the default events interface.
  795.  
  796.                 int nFlags;
  797.                 HREFTYPE hRefType;
  798.  
  799.                 for (unsigned int i = 0; i < pClassAttr->cImplTypes; i++)
  800.                 {
  801.                     if (SUCCEEDED(pClassInfo->GetImplTypeFlags(i, &nFlags)) &&
  802.                         ((nFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE))
  803.                     {
  804.                         // Found it.  Now look at its attributes to get IID.
  805.  
  806.                         LPTYPEINFO pEventInfo = NULL;
  807.  
  808.                         if (SUCCEEDED(pClassInfo->GetRefTypeOfImplType(i,
  809.                                 &hRefType)) &&
  810.                             SUCCEEDED(pClassInfo->GetRefTypeInfo(hRefType,
  811.                                 &pEventInfo)))
  812.                         {
  813.                             ASSERT(pEventInfo != NULL);
  814.  
  815.                             LPTYPEATTR pEventAttr;
  816.  
  817.                             if (SUCCEEDED(pEventInfo->GetTypeAttr(&pEventAttr)))
  818.                             {
  819.                                 ASSERT(pEventAttr != NULL);
  820.                                 *piid = pEventAttr->guid;
  821.                                 pEventInfo->ReleaseTypeAttr(pEventAttr);
  822.                             }
  823.  
  824.                             pEventInfo->Release();
  825.                         }
  826.  
  827.                         break;
  828.                     }
  829.                 }
  830.  
  831.                 pClassInfo->ReleaseTypeAttr(pClassAttr);
  832.             }
  833.  
  834.             pClassInfo->Release();
  835.         }
  836.  
  837.         pPCI->Release();
  838.     }
  839.  
  840.     return (!IsEqualIID(*piid, GUID_NULL));
  841. }
  842.  
  843. void COleControlSite::GetControlInfo()
  844. {
  845.     memset(&m_ctlInfo, 0, sizeof(CONTROLINFO));
  846.     m_ctlInfo.cb = sizeof(CONTROLINFO);
  847.     LPOLECONTROL pOleCtl = NULL;
  848.  
  849.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IOleControl,
  850.         (LPVOID*)&pOleCtl)))
  851.     {
  852.         ASSERT(pOleCtl != NULL);
  853.         pOleCtl->GetControlInfo(&m_ctlInfo);
  854.         pOleCtl->Release();
  855.     }
  856. }
  857.  
  858. #if defined(_WIN32_WCE)
  859. // WinCE: WinCE doesn't support CopyAcceleratorTable nor IsAcclerator, so we are going to 
  860. // use TranslateAccelerator, which is basically an IsAccelerator followed by a possible
  861. // SendMessage.  We want to eat any messages that might get sent by temporarily changing the
  862. // window procedure.  This is not thread-safe, but chance of another thread getting the
  863. // context switch AND sending a message to this particular control during that context
  864. // switch is almost nil.
  865. BOOL COleControlSite::IsMatchingMnemonic(LPMSG lpMsg)
  866. {
  867.     if ((m_ctlInfo.cAccel == 0) || (m_ctlInfo.hAccel == NULL))
  868.         return FALSE;
  869.     WNDPROC PrevWndProc = (WNDPROC)::SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)wce_IMMWndProc);
  870.     BOOL bMatch = ::TranslateAccelerator(m_hWnd,m_ctlInfo.hAccel,lpMsg);
  871.     ::SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)PrevWndProc);
  872.     return bMatch;
  873. }
  874. #else // _WIN32_WCE
  875. BOOL COleControlSite::IsMatchingMnemonic(LPMSG lpMsg)
  876. {
  877. //  return IsAccelerator(m_ctlInfo.hAccel, m_ctlInfo.cAccel, lpMsg, NULL);
  878.  
  879.     if ((m_ctlInfo.cAccel == 0) || (m_ctlInfo.hAccel == NULL))
  880.         return FALSE;
  881.  
  882.     ACCEL* pAccel = new ACCEL[m_ctlInfo.cAccel];
  883.     int cAccel = CopyAcceleratorTable(m_ctlInfo.hAccel, pAccel, m_ctlInfo.cAccel);
  884.     ASSERT(cAccel == m_ctlInfo.cAccel);
  885.  
  886.     BOOL bMatch = FALSE;
  887.     for (int i = 0; i < cAccel; i++)
  888.     {
  889.         BOOL fVirt = (lpMsg->message == WM_SYSCHAR ? FALT : 0);
  890.         WORD key = LOWORD(lpMsg->wParam);
  891.         if (((pAccel[i].fVirt & ~FNOINVERT) == fVirt) &&
  892.             (pAccel[i].key == key))
  893.         {
  894.             bMatch = TRUE;
  895.             break;
  896.         }
  897.     }
  898.  
  899.     delete [] pAccel;
  900.     return bMatch;
  901. }
  902. #endif // _WIN32_WCE
  903.  
  904. void COleControlSite::SendMnemonic(LPMSG lpMsg)
  905. {
  906.     if (!(m_dwMiscStatus & OLEMISC_NOUIACTIVATE))
  907.         SetFocus();
  908.  
  909.     LPOLECONTROL pOleCtl = NULL;
  910.  
  911.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IOleControl,
  912.         (LPVOID*)&pOleCtl)))
  913.     {
  914.         ASSERT(pOleCtl != NULL);
  915.         pOleCtl->OnMnemonic(lpMsg);
  916.         pOleCtl->Release();
  917.     }
  918. }
  919.  
  920. void COleControlSite::FreezeEvents(BOOL bFreeze)
  921. {
  922.     LPOLECONTROL pOleCtl = NULL;
  923.     if (SUCCEEDED(m_pObject->QueryInterface(IID_IOleControl,
  924.         (LPVOID*)&pOleCtl)))
  925.     {
  926.         ASSERT(pOleCtl != NULL);
  927.         pOleCtl->FreezeEvents(bFreeze);
  928.         pOleCtl->Release();
  929.     }
  930. }
  931.  
  932. void COleControlSite::AttachWindow()
  933. {
  934.     HWND hWnd = NULL;
  935.     if (SUCCEEDED(m_pInPlaceObject->GetWindow(&hWnd)))
  936.     {
  937.         ASSERT(hWnd != NULL);
  938.         if (m_hWnd != hWnd)
  939.         {
  940.             m_hWnd = hWnd;
  941.  
  942.             if (m_pWndCtrl != NULL)
  943.             {
  944.                 ASSERT(m_pWndCtrl->m_hWnd == NULL); // Window already attached?
  945.                 m_pWndCtrl->Attach(m_hWnd);
  946.  
  947.                 ASSERT(m_pWndCtrl->m_pCtrlSite == NULL ||
  948.                     m_pWndCtrl->m_pCtrlSite == this);
  949.                 m_pWndCtrl->m_pCtrlSite = this;
  950.             }
  951.         }
  952.     }
  953. }
  954.  
  955. void COleControlSite::DetachWindow()
  956. {
  957.     m_hWnd = NULL;
  958.  
  959.     if (m_pWndCtrl != NULL)
  960.     {
  961.         if (m_pWndCtrl->m_hWnd != NULL)
  962.         {
  963.             WNDPROC* lplpfn = m_pWndCtrl->GetSuperWndProcAddr();
  964.             ASSERT(lplpfn != NULL);
  965.             if (::IsWindow(m_pWndCtrl->m_hWnd) && *lplpfn != NULL)
  966.                 m_pWndCtrl->UnsubclassWindow();
  967.  
  968.             m_pWndCtrl->Detach();
  969.         }
  970.  
  971.         m_pWndCtrl->m_pCtrlSite = NULL;
  972.     }
  973. }
  974.  
  975. BOOL COleControlSite::OnEvent(AFX_EVENT* pEvent)
  976. {
  977.     // If this control has a proxy CWnd, look for a matching ON_*_REFLECT
  978.     // entry for this event in its event map.
  979.     if ((m_pWndCtrl != NULL) &&
  980.         m_pWndCtrl->OnCmdMsg(m_nID, CN_EVENT, pEvent, NULL))
  981.     {
  982.         return TRUE;
  983.     }
  984.  
  985.     // Proxy CWnd isn't interested, so pass the event along to the container.
  986.     return m_pCtrlCont->m_pWnd->OnCmdMsg(m_nID, CN_EVENT, pEvent, NULL);
  987. }
  988.  
  989. /////////////////////////////////////////////////////////////////////////////
  990. // invoke helpers
  991.  
  992. void COleControlSite::InvokeHelperV(DISPID dwDispID, WORD wFlags,
  993.     VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, va_list argList)
  994. {
  995.     if (m_dispDriver.m_lpDispatch == NULL)
  996.     {
  997.         // no dispatch pointer yet; find it now
  998.         LPDISPATCH pDispatch;
  999.  
  1000.         if ((m_pObject != NULL) &&
  1001.             SUCCEEDED(m_pObject->QueryInterface(IID_IDispatch,
  1002.                 (LPVOID*)&pDispatch)))
  1003.         {
  1004.             ASSERT(pDispatch != NULL);
  1005.             m_dispDriver.AttachDispatch(pDispatch);
  1006.         }
  1007.     }
  1008.  
  1009.     if (m_dispDriver.m_lpDispatch == NULL)
  1010.     {
  1011.         // couldn't find dispatch pointer
  1012.         TRACE0("Warning: control has no IDispatch interface.");
  1013.         return;
  1014.     }
  1015.  
  1016.     // delegate call to m_dispDriver
  1017.     m_dispDriver.InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo,
  1018.         argList);
  1019. }
  1020.  
  1021. void COleControlSite::SetPropertyV(DISPID dwDispID, VARTYPE vtProp, va_list argList)
  1022. {
  1023.     BYTE rgbParams[2];
  1024.     if (vtProp & VT_BYREF)
  1025.     {
  1026.         vtProp &= ~VT_BYREF;
  1027.         vtProp |= VT_MFCBYREF;
  1028.     }
  1029.  
  1030. #if !defined(_UNICODE) && !defined(OLE2ANSI)
  1031.     if (vtProp == VT_BSTR)
  1032.         vtProp = VT_BSTRA;
  1033. #endif
  1034.  
  1035.     WORD wFlags;
  1036.     if (vtProp & VT_MFCFORCEPUTREF)
  1037.     {
  1038.         wFlags = DISPATCH_PROPERTYPUTREF;
  1039.         vtProp &= ~VT_MFCFORCEPUTREF;
  1040.     }
  1041.     else
  1042.     {
  1043.         if (vtProp == VT_DISPATCH)
  1044.             wFlags = DISPATCH_PROPERTYPUTREF;
  1045.         else
  1046.             wFlags = DISPATCH_PROPERTYPUT;
  1047.     }
  1048.  
  1049.     rgbParams[0] = (BYTE)vtProp;
  1050.     rgbParams[1] = 0;
  1051.     InvokeHelperV(dwDispID, wFlags, VT_EMPTY, NULL, rgbParams, argList);
  1052. }
  1053.  
  1054. void AFX_CDECL COleControlSite::InvokeHelper(DISPID dwDispID, WORD wFlags, VARTYPE vtRet,
  1055.     void* pvRet, const BYTE* pbParamInfo, ...)
  1056. {
  1057.     va_list argList;
  1058.     va_start(argList, pbParamInfo);
  1059.     InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, argList);
  1060.     va_end(argList);
  1061. }
  1062.  
  1063. void COleControlSite::GetProperty(DISPID dwDispID, VARTYPE vtProp,
  1064.     void* pvProp) const
  1065. {
  1066.     const_cast<COleControlSite*>(this)->InvokeHelper(dwDispID,
  1067.         DISPATCH_PROPERTYGET, vtProp, pvProp, NULL);
  1068. }
  1069.  
  1070. void AFX_CDECL COleControlSite::SetProperty(DISPID dwDispID, VARTYPE vtProp, ...)
  1071. {
  1072.     va_list argList;    // really only one arg, but...
  1073.     va_start(argList, vtProp);
  1074.     SetPropertyV(dwDispID, vtProp, argList);
  1075.     va_end(argList);
  1076. }
  1077.  
  1078. BOOL AFX_CDECL COleControlSite::SafeSetProperty(DISPID dwDispID, VARTYPE vtProp, ...)
  1079. {
  1080.     va_list argList;    // really only one arg, but...
  1081.     va_start(argList, vtProp);
  1082.  
  1083.     BOOL bSuccess;
  1084.  
  1085.     TRY
  1086.     {
  1087.         SetPropertyV(dwDispID, vtProp, argList);
  1088.         bSuccess = TRUE;
  1089.     }
  1090.     CATCH_ALL(e)
  1091.     {
  1092.         DELETE_EXCEPTION(e);
  1093.         bSuccess = FALSE;
  1094.     }
  1095.     END_CATCH_ALL
  1096.  
  1097.     va_end(argList);
  1098.     return bSuccess;
  1099. }
  1100.  
  1101. /////////////////////////////////////////////////////////////////////////////
  1102. // special cases for CWnd functions
  1103.  
  1104. DWORD COleControlSite::GetStyle() const
  1105. {
  1106.     DWORD dwStyle = m_dwStyle |
  1107.         (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_VISIBLE);
  1108.  
  1109.     TRY
  1110.     {
  1111.         BOOL bEnabled = TRUE;
  1112.         GetProperty(DISPID_ENABLED, VT_BOOL, &bEnabled);
  1113.         if (!bEnabled)
  1114.             dwStyle |= WS_DISABLED;
  1115.     }
  1116.     END_TRY
  1117.  
  1118.     TRY
  1119.     {
  1120.         short sBorderStyle = 0;
  1121.         GetProperty(DISPID_BORDERSTYLE, VT_I2, &sBorderStyle);
  1122.         if (sBorderStyle == 1)
  1123.             dwStyle |= WS_BORDER;
  1124.     }
  1125.     END_TRY
  1126.  
  1127.     return dwStyle;
  1128. }
  1129.  
  1130. DWORD COleControlSite::GetExStyle() const
  1131. {
  1132.     DWORD dwExStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  1133.  
  1134.     TRY
  1135.     {
  1136.         short sAppearance = 0;
  1137.         GetProperty(DISPID_APPEARANCE, VT_I2, &sAppearance);
  1138.         if (sAppearance == 1)
  1139.             dwExStyle |= WS_EX_CLIENTEDGE;
  1140.     }
  1141.     END_TRY
  1142.  
  1143.     return dwExStyle;
  1144. }
  1145.  
  1146. BOOL COleControlSite::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  1147. {
  1148.     m_dwStyle = ((m_dwStyle & ~dwRemove) | dwAdd) & m_dwStyleMask;
  1149.  
  1150.     // Enabled property
  1151.     if ((dwRemove & WS_DISABLED) || (dwAdd & WS_DISABLED))
  1152.     {
  1153.         if (SafeSetProperty(DISPID_ENABLED, VT_BOOL, (~dwAdd & WS_DISABLED)))
  1154.         {
  1155.             dwRemove &= ~WS_DISABLED;
  1156.             dwAdd &= ~WS_DISABLED;
  1157.         }
  1158.     }
  1159.  
  1160.     // BorderStyle property
  1161.     if ((dwRemove & WS_BORDER) || (dwAdd & WS_BORDER))
  1162.     {
  1163.         if (SafeSetProperty(DISPID_BORDERSTYLE, VT_I2, (dwAdd & WS_BORDER)))
  1164.         {
  1165.             dwRemove &= ~WS_BORDER;
  1166.             dwAdd &= ~WS_BORDER;
  1167.         }
  1168.     }
  1169.  
  1170.     return CWnd::ModifyStyle(m_hWnd, dwRemove, dwAdd, nFlags);
  1171. }
  1172.  
  1173. BOOL COleControlSite::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  1174. {
  1175.     // BorderStyle property
  1176.     if ((dwRemove & WS_EX_CLIENTEDGE) || (dwAdd & WS_EX_CLIENTEDGE))
  1177.     {
  1178.         if (SafeSetProperty(DISPID_APPEARANCE, VT_I2, (dwAdd & WS_EX_CLIENTEDGE)))
  1179.         {
  1180.             dwRemove &= ~WS_EX_CLIENTEDGE;
  1181.             dwAdd &= ~WS_EX_CLIENTEDGE;
  1182.         }
  1183.     }
  1184.  
  1185.     return CWnd::ModifyStyleEx(m_hWnd, dwRemove, dwAdd, nFlags);
  1186. }
  1187.  
  1188. void COleControlSite::SetWindowText(LPCTSTR lpszString)
  1189. {
  1190.     ASSERT(::IsWindow(m_hWnd));
  1191.  
  1192.     if (!SafeSetProperty(DISPID_CAPTION, VT_BSTR, lpszString))
  1193.         SafeSetProperty(DISPID_TEXT, VT_BSTR, lpszString);
  1194. }
  1195.  
  1196. void COleControlSite::GetWindowText(CString& str) const
  1197. {
  1198.     ASSERT(::IsWindow(m_hWnd));
  1199.  
  1200.     TRY
  1201.     {
  1202.         GetProperty(DISPID_CAPTION, VT_BSTR, &str);
  1203.     }
  1204.     CATCH_ALL(e)
  1205.     {
  1206.         DELETE_EXCEPTION(e);
  1207.  
  1208.         TRY
  1209.         {
  1210.             GetProperty(DISPID_TEXT, VT_BSTR, &str);
  1211.         }
  1212.         END_TRY
  1213.     }
  1214.     END_CATCH_ALL
  1215. }
  1216.  
  1217. int COleControlSite::GetWindowText(LPTSTR lpszString, int nMaxCount) const
  1218. {
  1219.     ASSERT(nMaxCount > 0);
  1220.     CString str;
  1221.     GetWindowText(str);
  1222.     lstrcpyn(lpszString, str, nMaxCount);
  1223.     return lstrlen(lpszString);
  1224. }
  1225.  
  1226. int COleControlSite::GetWindowTextLength() const
  1227. {
  1228.     CString str;
  1229.     GetWindowText(str);
  1230.     return str.GetLength();
  1231. }
  1232.  
  1233. int COleControlSite::GetDlgCtrlID() const
  1234. {
  1235.     return (int)m_nID;
  1236. }
  1237.  
  1238. int COleControlSite::SetDlgCtrlID(int nID)
  1239. {
  1240.     int nPrevID = (int)m_nID;
  1241.     m_nID = (UINT)nID;
  1242.     return nPrevID;
  1243. }
  1244.  
  1245. void COleControlSite::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL)
  1246. {
  1247.     ASSERT(m_pInPlaceObject != NULL);
  1248.     ASSERT(m_pObject != NULL);
  1249.  
  1250.     CRect rectOld(m_rect);
  1251.     m_rect.SetRect(x, y, x + nWidth, y + nHeight);
  1252.     if (SetExtent())
  1253.     {
  1254.         m_rect.SetRect(x, y, x + m_rect.Width(), y + m_rect.Height());
  1255.         m_pInPlaceObject->SetObjectRects(m_rect, m_rect);
  1256.     }
  1257.     else
  1258.     {
  1259.         m_rect = rectOld;
  1260.     }
  1261. }
  1262.  
  1263. BOOL COleControlSite::SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx,
  1264.     int cy, UINT nFlags)
  1265. {
  1266.     if (nFlags & SWP_HIDEWINDOW)
  1267.         ShowWindow(SW_HIDE);
  1268.  
  1269.     if ((nFlags & (SWP_NOMOVE|SWP_NOSIZE)) != (SWP_NOMOVE|SWP_NOSIZE))
  1270.     {
  1271.         int xNew;
  1272.         int yNew;
  1273.         if (nFlags & SWP_NOMOVE)
  1274.         {
  1275.             xNew = m_rect.left;
  1276.             yNew = m_rect.top;
  1277.         }
  1278.         else
  1279.         {
  1280.             xNew = x;
  1281.             yNew = y;
  1282.         }
  1283.  
  1284.         int cxNew;
  1285.         int cyNew;
  1286.         if (nFlags & SWP_NOSIZE)
  1287.         {
  1288.             cxNew = m_rect.Width();
  1289.             cyNew = m_rect.Height();
  1290.         }
  1291.         else
  1292.         {
  1293.             cxNew = cx;
  1294.             cyNew = cy;
  1295.         }
  1296.  
  1297.         MoveWindow(xNew, yNew, cxNew, cyNew, !(nFlags & SWP_NOREDRAW));
  1298.     }
  1299.  
  1300.     if (nFlags & SWP_SHOWWINDOW)
  1301.         ShowWindow(SW_SHOW);
  1302.  
  1303.     // we've handled hide, move, size, and show; let Windows do the rest
  1304.     nFlags &= ~(SWP_HIDEWINDOW|SWP_SHOWWINDOW);
  1305.     nFlags |= (SWP_NOMOVE|SWP_NOSIZE);
  1306.     return ::SetWindowPos(m_hWnd, pWndInsertAfter->GetSafeHwnd(),
  1307.         x, y, cx, cy, nFlags);
  1308. }
  1309.  
  1310. BOOL COleControlSite::ShowWindow(int nCmdShow)
  1311. {
  1312.     BOOL bReturn = ::IsWindowVisible(m_hWnd);
  1313.     int iVerb = 0;
  1314.     switch (nCmdShow)
  1315.     {
  1316.     case SW_SHOW:
  1317.     case SW_SHOWNORMAL:
  1318.     case SW_SHOWNOACTIVATE:
  1319.         iVerb = OLEIVERB_SHOW;
  1320.         break;
  1321.  
  1322.     case SW_HIDE:
  1323.         iVerb = OLEIVERB_HIDE;
  1324.         break;
  1325.     }
  1326.  
  1327.     if (iVerb != 0)
  1328.         DoVerb(iVerb);
  1329.  
  1330.     return bReturn;
  1331. }
  1332.  
  1333. BOOL COleControlSite::IsWindowEnabled() const
  1334. {
  1335.     BOOL bEnabled = TRUE;
  1336.     TRY
  1337.         GetProperty(DISPID_ENABLED, VT_BOOL, &bEnabled);
  1338.     END_TRY
  1339.  
  1340.     return bEnabled;
  1341. }
  1342.  
  1343. BOOL COleControlSite::EnableWindow(BOOL bEnable)
  1344. {
  1345.     BOOL bResult;
  1346.     TRY
  1347.     {
  1348.         GetProperty(DISPID_ENABLED, VT_BOOL, &bResult);
  1349.         SetProperty(DISPID_ENABLED, VT_BOOL, DISPATCH_PROPERTYPUT, bEnable);
  1350.     }
  1351.     CATCH_ALL(e)
  1352.     {
  1353.         DELETE_EXCEPTION(e);
  1354.         bResult = TRUE;
  1355.     }
  1356.     END_CATCH_ALL
  1357.  
  1358.     return !bResult;    // return TRUE if previously disabled
  1359. }
  1360.  
  1361. CWnd* COleControlSite::SetFocus()
  1362. {
  1363.     if (m_dwMiscStatus & OLEMISC_NOUIACTIVATE)
  1364.         return CWnd::FromHandle(::SetFocus(m_hWnd));
  1365.  
  1366.     CWnd* pWndPrev = CWnd::GetFocus();
  1367.     DoVerb(OLEIVERB_UIACTIVATE);
  1368.     return pWndPrev;
  1369. }
  1370.  
  1371. #if !defined(_WIN32_WCE)
  1372. void COleControlSite::EnableDSC()
  1373. {
  1374.     if (m_pDataSourceControl == NULL)
  1375.     {
  1376.         m_pDataSourceControl = new CDataSourceControl(this);
  1377.         m_pDataSourceControl->Initialize();
  1378.     }
  1379. }
  1380.  
  1381. void COleControlSite::BindDefaultProperty(DISPID dwDispID, VARTYPE vtProp, LPCTSTR szFieldName, CWnd* pDSCWnd)
  1382. {
  1383.     // Remove any previous binding
  1384.     if (m_pDSCSite)
  1385.     {
  1386.         m_pDSCSite->m_pDataSourceControl->BindProp(this, FALSE);
  1387.         m_pDSCSite->m_pDataSourceControl->BindColumns();
  1388.     }
  1389.  
  1390.     m_pDSCSite = NULL;
  1391.  
  1392.     if (pDSCWnd)
  1393.     {
  1394.         ASSERT(pDSCWnd->m_pCtrlSite);  // must be an OLE control
  1395.         pDSCWnd->m_pCtrlSite->EnableDSC();
  1396.         m_pDSCSite = pDSCWnd->m_pCtrlSite;
  1397.         m_defdispid = dwDispID;
  1398.         m_dwType = vtProp;
  1399.         m_strDataField = szFieldName;
  1400.         m_pDSCSite->m_pDataSourceControl->BindProp(this, TRUE);
  1401.         m_pDSCSite->m_pDataSourceControl->BindColumns();
  1402.     }
  1403. }
  1404.  
  1405. void COleControlSite::BindProperty(DISPID dwDispId, CWnd* pWndDSC)
  1406. {
  1407.     ASSERT(pWndDSC == NULL || pWndDSC->m_pCtrlSite);
  1408.     if (pWndDSC != NULL && dwDispId != DISPID_UNKNOWN)
  1409.     {
  1410.         m_pBindings = new CDataBoundProperty(m_pBindings, dwDispId, 0);
  1411.         m_pBindings->m_pDSCSite = pWndDSC->m_pCtrlSite;
  1412.         m_pBindings->m_pClientSite = this;
  1413.         m_pBindings->m_pDSCSite->EnableDSC();
  1414.         m_pBindings->m_pDSCSite->m_pDataSourceControl->BindProp(m_pBindings, TRUE);
  1415.     }
  1416.     else
  1417.     {
  1418.         // Try and locate the particular property to unbind
  1419.         // if dwDispId == DISPID_UNKNOWN && pWndDSC == NULL it unbinds all properties
  1420.         // if dwDispId == DISPID_UNKNOWN && pWndDSC != NULL it unbinds properties for that DSC
  1421.         CDataBoundProperty *pCurrent = m_pBindings;
  1422.         CDataBoundProperty* pPrev = NULL;
  1423.         while (pCurrent != NULL)
  1424.         {
  1425.             CDataBoundProperty* pNext = pCurrent->GetNext();
  1426.             if (dwDispId == DISPID_UNKNOWN || pCurrent->m_dispid == dwDispId)
  1427.             {
  1428.                 if (pWndDSC == NULL || pWndDSC->m_pCtrlSite == pCurrent->m_pDSCSite)
  1429.                 {
  1430.                     if (pPrev != NULL)
  1431.                         pPrev->m_pNext = pNext;
  1432.                     else
  1433.                         m_pBindings = pNext;
  1434.                     if (pCurrent->m_pDSCSite != NULL && pCurrent->m_pDSCSite->m_pDataSourceControl != NULL)
  1435.                         pCurrent->m_pDSCSite->m_pDataSourceControl->BindProp(pCurrent, FALSE);
  1436.                     delete pCurrent;
  1437.                 }
  1438.             }
  1439.             if (pPrev != NULL)
  1440.                 pPrev = pPrev->GetNext();
  1441.             pCurrent = pNext;
  1442.         }
  1443.     }
  1444. }
  1445. #endif // _WIN32_WCE
  1446.  
  1447.  
  1448. /////////////////////////////////////////////////////////////////////////////
  1449. // COleControlSite::XOleClientSite
  1450.  
  1451. STDMETHODIMP_(ULONG) COleControlSite::XOleClientSite::AddRef()
  1452. {
  1453.     METHOD_PROLOGUE_EX_(COleControlSite, OleClientSite)
  1454.     return (ULONG)pThis->InternalAddRef();
  1455. }
  1456.  
  1457. STDMETHODIMP_(ULONG) COleControlSite::XOleClientSite::Release()
  1458. {
  1459.     METHOD_PROLOGUE_EX_(COleControlSite, OleClientSite)
  1460.     return (ULONG)pThis->InternalRelease();
  1461. }
  1462.  
  1463. STDMETHODIMP COleControlSite::XOleClientSite::QueryInterface(
  1464.     REFIID iid, LPVOID* ppvObj)
  1465. {
  1466.     METHOD_PROLOGUE_EX_(COleControlSite, OleClientSite)
  1467.     return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  1468. }
  1469.  
  1470. STDMETHODIMP COleControlSite::XOleClientSite::SaveObject()
  1471. {
  1472.     return E_NOTIMPL;
  1473. }
  1474.  
  1475. STDMETHODIMP COleControlSite::XOleClientSite::GetMoniker(DWORD, DWORD,
  1476.     LPMONIKER*)
  1477. {
  1478.     return E_NOTIMPL;
  1479. }
  1480.  
  1481. STDMETHODIMP COleControlSite::XOleClientSite::GetContainer(
  1482.     LPOLECONTAINER* ppContainer)
  1483. {
  1484.     METHOD_PROLOGUE_EX_(COleControlSite, OleClientSite)
  1485.     return (HRESULT)pThis->m_pCtrlCont->InternalQueryInterface(
  1486.         &IID_IOleContainer, (LPVOID*)ppContainer);
  1487. }
  1488.  
  1489. STDMETHODIMP COleControlSite::XOleClientSite::ShowObject()
  1490. {
  1491.     METHOD_PROLOGUE_EX(COleControlSite, OleClientSite)
  1492.     pThis->AttachWindow();
  1493.     return S_OK;
  1494. }
  1495.  
  1496. STDMETHODIMP COleControlSite::XOleClientSite::OnShowWindow(BOOL)
  1497. {
  1498.     return S_OK;
  1499. }
  1500.  
  1501. STDMETHODIMP COleControlSite::XOleClientSite::RequestNewObjectLayout()
  1502. {
  1503.     return E_NOTIMPL;
  1504. }
  1505.  
  1506.  
  1507. /////////////////////////////////////////////////////////////////////////////
  1508. // COleControlSite::XOleIPSite
  1509.  
  1510. STDMETHODIMP_(ULONG) COleControlSite::XOleIPSite::AddRef()
  1511. {
  1512.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1513.     return (ULONG)pThis->InternalAddRef();
  1514. }
  1515.  
  1516. STDMETHODIMP_(ULONG) COleControlSite::XOleIPSite::Release()
  1517. {
  1518.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1519.     return (ULONG)pThis->InternalRelease();
  1520. }
  1521.  
  1522. STDMETHODIMP COleControlSite::XOleIPSite::QueryInterface(
  1523.     REFIID iid, LPVOID* ppvObj)
  1524. {
  1525.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1526.     return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  1527. }
  1528.  
  1529. STDMETHODIMP COleControlSite::XOleIPSite::GetWindow(HWND* phWnd)
  1530. {
  1531.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1532.     *phWnd = pThis->m_pCtrlCont->m_pWnd->GetSafeHwnd();
  1533.     return *phWnd != NULL ? S_OK : E_FAIL;
  1534. }
  1535.  
  1536. STDMETHODIMP COleControlSite::XOleIPSite::ContextSensitiveHelp(BOOL)
  1537. {
  1538.     return E_NOTIMPL;
  1539. }
  1540.  
  1541. STDMETHODIMP COleControlSite::XOleIPSite::CanInPlaceActivate()
  1542. {
  1543.     return S_OK;
  1544. }
  1545.  
  1546. STDMETHODIMP COleControlSite::XOleIPSite::OnInPlaceActivate()
  1547. {
  1548.     return S_OK;
  1549. }
  1550.  
  1551. STDMETHODIMP COleControlSite::XOleIPSite::OnUIActivate()
  1552. {
  1553.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1554.     pThis->m_pCtrlCont->OnUIActivate(pThis);
  1555.     return S_OK;
  1556. }
  1557.  
  1558. STDMETHODIMP COleControlSite::XOleIPSite::GetWindowContext(
  1559.     LPOLEINPLACEFRAME* ppFrame, LPOLEINPLACEUIWINDOW* ppDoc, LPRECT prectPos,
  1560.     LPRECT prectClip, LPOLEINPLACEFRAMEINFO pFrameInfo)
  1561. {
  1562.     METHOD_PROLOGUE_EX(COleControlSite, OleIPSite)
  1563.     ASSERT_VALID(pThis->m_pCtrlCont);
  1564.     ASSERT_VALID(pThis->m_pCtrlCont->m_pWnd);
  1565.  
  1566.     ASSERT(AfxIsValidAddress(ppFrame, sizeof(LPOLEINPLACEFRAME)));
  1567.     ASSERT((ppDoc == NULL) ||
  1568.         AfxIsValidAddress(ppDoc, sizeof(LPOLEINPLACEUIWINDOW)));
  1569.     ASSERT(AfxIsValidAddress(prectPos, sizeof(RECT)));
  1570.     ASSERT(AfxIsValidAddress(prectClip, sizeof(RECT)));
  1571.     ASSERT(AfxIsValidAddress(pFrameInfo, pFrameInfo->cb));
  1572.  
  1573.     //WINBUG: This is a temporary patch for IE3 beta.  When IE3 is fixed, this
  1574.     // assert can be re-enabled.  Otherwise it fires everytime you browse via
  1575.     // the CWebBrowser control.
  1576.     //
  1577.     //  ASSERT(pFrameInfo->cb >= offsetof(OLEINPLACEFRAMEINFO, cAccelEntries) +
  1578.     //          sizeof(int));
  1579.  
  1580.     // There is no separate doc window
  1581.     if (ppDoc != NULL)
  1582.         *ppDoc = NULL;
  1583.  
  1584.     // Set pointer to frame
  1585.     if (FAILED(pThis->m_pCtrlCont->InternalQueryInterface(
  1586.         &IID_IOleInPlaceFrame, (LPVOID*)ppFrame)))
  1587.         return E_FAIL;
  1588.  
  1589.     // Fill in position and clip rectangles
  1590.     CWnd* pWndContainer = pThis->m_pCtrlCont->m_pWnd;
  1591.     CopyRect(prectPos, pThis->m_rect);
  1592.     pWndContainer->GetClientRect(prectClip);
  1593.  
  1594.     // Fill in frame info
  1595.     pFrameInfo->fMDIApp = FALSE;
  1596.     pFrameInfo->hwndFrame = pWndContainer->GetSafeHwnd();
  1597.     pFrameInfo->haccel = NULL;
  1598.     pFrameInfo->cAccelEntries = 0;
  1599.  
  1600.     return S_OK;
  1601. }
  1602.  
  1603. STDMETHODIMP COleControlSite::XOleIPSite::Scroll(SIZE)
  1604. {
  1605.     return S_FALSE;
  1606. }
  1607.  
  1608. STDMETHODIMP COleControlSite::XOleIPSite::OnUIDeactivate(BOOL)
  1609. {
  1610.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1611.     pThis->m_pCtrlCont->OnUIDeactivate(pThis);
  1612.     return S_OK;
  1613. }
  1614.  
  1615. STDMETHODIMP COleControlSite::XOleIPSite::OnInPlaceDeactivate()
  1616. {
  1617.     METHOD_PROLOGUE_EX(COleControlSite, OleIPSite)
  1618.     pThis->DetachWindow();
  1619.     return S_OK;
  1620. }
  1621.  
  1622. STDMETHODIMP COleControlSite::XOleIPSite::DiscardUndoState()
  1623. {
  1624.     return S_OK;
  1625. }
  1626.  
  1627. STDMETHODIMP COleControlSite::XOleIPSite::DeactivateAndUndo()
  1628. {
  1629.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1630.     pThis->m_pInPlaceObject->UIDeactivate();
  1631.     return S_OK;
  1632. }
  1633.  
  1634. STDMETHODIMP COleControlSite::XOleIPSite::OnPosRectChange(LPCRECT lprcPosRect)
  1635. {
  1636.     METHOD_PROLOGUE_EX_(COleControlSite, OleIPSite)
  1637.     CRect rectClip;
  1638.     pThis->m_pCtrlCont->m_pWnd->GetClientRect(rectClip);
  1639.     pThis->m_rect = lprcPosRect;
  1640.     return pThis->m_pInPlaceObject->SetObjectRects(pThis->m_rect, rectClip);
  1641. }
  1642.  
  1643.  
  1644. /////////////////////////////////////////////////////////////////////////////
  1645. // COleControlSite::XOleControlSite
  1646.  
  1647. STDMETHODIMP_(ULONG) COleControlSite::XOleControlSite::AddRef()
  1648. {
  1649.     METHOD_PROLOGUE_EX_(COleControlSite, OleControlSite)
  1650.     return (ULONG)pThis->InternalAddRef();
  1651. }
  1652.  
  1653. STDMETHODIMP_(ULONG) COleControlSite::XOleControlSite::Release()
  1654. {
  1655.     METHOD_PROLOGUE_EX_(COleControlSite, OleControlSite)
  1656.     return (ULONG)pThis->InternalRelease();
  1657. }
  1658.  
  1659. STDMETHODIMP COleControlSite::XOleControlSite::QueryInterface(
  1660.     REFIID iid, LPVOID* ppvObj)
  1661. {
  1662.     METHOD_PROLOGUE_EX_(COleControlSite, OleControlSite)
  1663.     return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  1664. }
  1665.  
  1666. STDMETHODIMP COleControlSite::XOleControlSite::OnControlInfoChanged()
  1667. {
  1668.     METHOD_PROLOGUE_EX_(COleControlSite, OleControlSite)
  1669.     pThis->GetControlInfo();
  1670.     return NOERROR;
  1671. }
  1672.  
  1673. STDMETHODIMP COleControlSite::XOleControlSite::LockInPlaceActive(BOOL)
  1674. {
  1675.     return E_NOTIMPL;
  1676. }
  1677.  
  1678. STDMETHODIMP COleControlSite::XOleControlSite::GetExtendedControl(
  1679.     LPDISPATCH*)
  1680. {
  1681.     return E_NOTIMPL;
  1682. }
  1683.  
  1684. STDMETHODIMP COleControlSite::XOleControlSite::TransformCoords(
  1685.     POINTL* pptHimetric, POINTF* pptContainer, DWORD dwFlags)
  1686. {
  1687.     METHOD_PROLOGUE_EX_(COleControlSite, OleControlSite)
  1688.     HRESULT hr = NOERROR;
  1689.  
  1690.     HDC hDC = ::GetDC(pThis->m_hWnd);
  1691. #if !defined(_WIN32_WCE) 
  1692.     // WinCE: We will use alternative coordinate transformation
  1693.     // functions (see below)
  1694.     ::SetMapMode(hDC, MM_HIMETRIC);
  1695. #endif // _WIN32_WCE
  1696.     POINT rgptConvert[2];
  1697.     rgptConvert[0].x = 0;
  1698.     rgptConvert[0].y = 0;
  1699.  
  1700.     if (dwFlags & XFORMCOORDS_HIMETRICTOCONTAINER)
  1701.     {
  1702.         rgptConvert[1].x = pptHimetric->x;
  1703.         rgptConvert[1].y = pptHimetric->y;
  1704. #if defined(_WIN32_WCE)
  1705.         CDC dc;
  1706.         dc.Attach(hDC);
  1707.         dc.HIMETRICtoDP((LPSIZE)(&rgptConvert[0]));
  1708.          dc.HIMETRICtoDP((LPSIZE)(&rgptConvert[1]));
  1709. #else // _WIN32_WCE
  1710.         ::LPtoDP(hDC, rgptConvert, 2);
  1711. #endif // _WIN32_WCE
  1712.         if (dwFlags & XFORMCOORDS_SIZE)
  1713.         {
  1714.             pptContainer->x = (float)(rgptConvert[1].x - rgptConvert[0].x);
  1715.             pptContainer->y = (float)(rgptConvert[0].y - rgptConvert[1].y);
  1716.         }
  1717.         else if (dwFlags & XFORMCOORDS_POSITION)
  1718.         {
  1719.             pptContainer->x = (float)rgptConvert[1].x;
  1720.             pptContainer->y = (float)rgptConvert[1].y;
  1721.         }
  1722.         else
  1723.         {
  1724.             hr = E_INVALIDARG;
  1725.         }
  1726.     }
  1727.     else if (dwFlags & XFORMCOORDS_CONTAINERTOHIMETRIC)
  1728.     {
  1729.         rgptConvert[1].x = (int)(pptContainer->x);
  1730.         rgptConvert[1].y = (int)(pptContainer->y);
  1731. #if defined(_WIN32_WCE)
  1732.         CDC dc;
  1733.         dc.Attach(hDC);
  1734.         dc.DPtoHIMETRIC((LPSIZE)(&rgptConvert[0]));
  1735.          dc.DPtoHIMETRIC((LPSIZE)(&rgptConvert[1]));
  1736. #else // _WIN32_WCE
  1737.         ::DPtoLP(hDC, rgptConvert, 2);
  1738. #endif // _WIN32_WCE
  1739.         if (dwFlags & XFORMCOORDS_SIZE)
  1740.         {
  1741.             pptHimetric->x = rgptConvert[1].x - rgptConvert[0].x;
  1742.             pptHimetric->y = rgptConvert[0].y - rgptConvert[1].y;
  1743.         }
  1744.         else if (dwFlags & XFORMCOORDS_POSITION)
  1745.         {
  1746.             pptHimetric->x = rgptConvert[1].x;
  1747.             pptHimetric->y = rgptConvert[1].y;
  1748.         }
  1749.         else
  1750.         {
  1751.             hr = E_INVALIDARG;
  1752.         }
  1753.     }
  1754.     else
  1755.     {
  1756.         hr = E_INVALIDARG;
  1757.     }
  1758.  
  1759.     ::ReleaseDC(pThis->m_hWnd, hDC);
  1760.  
  1761.     return hr;
  1762. }
  1763.  
  1764. STDMETHODIMP COleControlSite::XOleControlSite::TranslateAccelerator(
  1765.     LPMSG, DWORD)
  1766. {
  1767.     return E_NOTIMPL;
  1768. }
  1769.  
  1770. STDMETHODIMP COleControlSite::XOleControlSite::OnFocus(BOOL)
  1771. {
  1772.     return S_OK;
  1773. }
  1774.  
  1775. STDMETHODIMP COleControlSite::XOleControlSite::ShowPropertyFrame()
  1776. {
  1777.     return E_NOTIMPL;
  1778. }
  1779.  
  1780. /////////////////////////////////////////////////////////////////////////////
  1781. // COleControlSite::XAmbientProps
  1782.  
  1783. STDMETHODIMP_(ULONG) COleControlSite::XAmbientProps::AddRef()
  1784. {
  1785.     METHOD_PROLOGUE_EX_(COleControlSite, AmbientProps)
  1786.     return (ULONG)pThis->InternalAddRef();
  1787. }
  1788.  
  1789. STDMETHODIMP_(ULONG) COleControlSite::XAmbientProps::Release()
  1790. {
  1791.     METHOD_PROLOGUE_EX_(COleControlSite, AmbientProps)
  1792.     return (ULONG)pThis->InternalRelease();
  1793. }
  1794.  
  1795. STDMETHODIMP COleControlSite::XAmbientProps::QueryInterface(
  1796.     REFIID iid, LPVOID* ppvObj)
  1797. {
  1798.     METHOD_PROLOGUE_EX_(COleControlSite, AmbientProps)
  1799.     return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  1800. }
  1801.  
  1802. STDMETHODIMP COleControlSite::XAmbientProps::GetTypeInfoCount(
  1803.     unsigned int*)
  1804. {
  1805.     return E_NOTIMPL;
  1806. }
  1807.  
  1808. STDMETHODIMP COleControlSite::XAmbientProps::GetTypeInfo(
  1809.     unsigned int, LCID, ITypeInfo**)
  1810. {
  1811.     return E_NOTIMPL;
  1812. }
  1813.  
  1814. STDMETHODIMP COleControlSite::XAmbientProps::GetIDsOfNames(
  1815.     REFIID, LPOLESTR*, unsigned int, LCID, DISPID*)
  1816. {
  1817.     return E_NOTIMPL;
  1818. }
  1819.  
  1820. STDMETHODIMP COleControlSite::XAmbientProps::Invoke(
  1821.     DISPID dispid, REFIID, LCID, unsigned short wFlags,
  1822.     DISPPARAMS* pDispParams, VARIANT* pvarResult,
  1823.     EXCEPINFO*, unsigned int*)
  1824. {
  1825.     UNUSED(wFlags);
  1826.     UNUSED(pDispParams);
  1827.  
  1828.     METHOD_PROLOGUE_EX(COleControlSite, AmbientProps)
  1829.     ASSERT(wFlags & DISPATCH_PROPERTYGET);
  1830.     ASSERT(pDispParams->cArgs == 0);
  1831.  
  1832.     ASSERT(pThis->m_pCtrlCont != NULL);
  1833.     ASSERT(pThis->m_pCtrlCont->m_pWnd != NULL);
  1834.  
  1835.     return pThis->m_pCtrlCont->m_pWnd->OnAmbientProperty(pThis, dispid, pvarResult) ?
  1836.         S_OK : DISP_E_MEMBERNOTFOUND;
  1837. }
  1838.  
  1839.  
  1840. /////////////////////////////////////////////////////////////////////////////
  1841. // COleControlSite::XPropertyNotifySink
  1842.  
  1843. STDMETHODIMP COleControlSite::XPropertyNotifySink::QueryInterface(
  1844.     REFIID iid, LPVOID* ppvObj)
  1845. {
  1846.     METHOD_PROLOGUE_EX_(COleControlSite, PropertyNotifySink)
  1847.  
  1848.     if (IsEqualIID(iid, IID_IUnknown) ||
  1849.         IsEqualIID(iid, IID_IPropertyNotifySink))
  1850.     {
  1851.         *ppvObj = this;
  1852.         AddRef();
  1853.         return S_OK;
  1854.     }
  1855.     else
  1856.     {
  1857.         return E_NOINTERFACE;
  1858.     }
  1859. }
  1860.  
  1861. STDMETHODIMP_(ULONG) COleControlSite::XPropertyNotifySink::AddRef()
  1862. {
  1863.     return 1;
  1864. }
  1865.  
  1866. STDMETHODIMP_(ULONG) COleControlSite::XPropertyNotifySink::Release()
  1867. {
  1868.     return 0;
  1869. }
  1870.  
  1871. STDMETHODIMP COleControlSite::XPropertyNotifySink::OnChanged(
  1872.     DISPID dispid)
  1873. {
  1874.     METHOD_PROLOGUE_EX(COleControlSite, PropertyNotifySink)
  1875.  
  1876. #if !defined(_WIN32_WCE)
  1877.         // If we are currently updating the control ignore notifications
  1878.     if (pThis->m_bIgnoreNotify)
  1879.         return S_OK;
  1880.  
  1881.     // Give user chance to override
  1882.     if (!pThis->m_pDataSourceControl)
  1883. #endif // _WIN32_WCE
  1884.     {
  1885.         AFX_EVENT event(AFX_EVENT::propChanged, dispid);
  1886.         pThis->OnEvent(&event);
  1887.         if (event.m_hResult != S_OK)
  1888.             return event.m_hResult;
  1889.     }
  1890.  
  1891.     if (WCE_IF(TRUE, pThis->m_defdispid == dispid))
  1892.     {
  1893.         ::VariantClear(&pThis->m_varResult);
  1894.  
  1895.         HRESULT hRes;
  1896.         LPDISPATCH pDispatch = NULL;
  1897.         hRes = pThis->m_pObject->QueryInterface(IID_IDispatch, (LPVOID *) &pDispatch);
  1898.         if (FAILED(hRes))
  1899.             return S_OK;
  1900.  
  1901.         EXCEPINFO excepinfo;
  1902.         memset(&excepinfo, 0, sizeof(EXCEPINFO));
  1903.         UINT uArgErr;
  1904.         DISPPARAMS dispparamsGetProp;
  1905.         memset (&dispparamsGetProp, 0, sizeof(DISPPARAMS));
  1906.         hRes = pDispatch->Invoke(dispid, IID_NULL, 0, INVOKE_PROPERTYGET, &dispparamsGetProp,
  1907.                 &pThis->m_varResult, &excepinfo, &uArgErr); //Get bound control property
  1908.  
  1909.         if (excepinfo.bstrSource)
  1910.             SysFreeString(excepinfo.bstrSource);
  1911.         if (excepinfo.bstrDescription)
  1912.             SysFreeString(excepinfo.bstrDescription);
  1913.         if (excepinfo.bstrHelpFile)
  1914.             SysFreeString(excepinfo.bstrHelpFile);
  1915.  
  1916.         pDispatch->Release();
  1917.  
  1918.         if (FAILED(hRes))
  1919.             return S_OK;
  1920.  
  1921. #if !defined(_WIN32_WCE)
  1922.         pThis->m_bIsDirty = TRUE;
  1923. #endif // _WIN32_WCE
  1924.     }
  1925.  
  1926.     return S_OK;
  1927. }
  1928.  
  1929. STDMETHODIMP COleControlSite::XPropertyNotifySink::OnRequestEdit(
  1930.     DISPID dispid)
  1931. {
  1932.     METHOD_PROLOGUE_EX(COleControlSite, PropertyNotifySink)
  1933.  
  1934. #if !defined(_WIN32_WCE)
  1935.     // If we are currently updating the control ignore notifications
  1936.     if (pThis->m_bIgnoreNotify)
  1937.         return S_OK;
  1938.  
  1939.     // If not bound fire regular MFC event
  1940.     if (!pThis->m_pDataSourceControl)
  1941. #endif // _WIN32_WCE
  1942.     {
  1943.         AFX_EVENT event(AFX_EVENT::propRequest, dispid);
  1944.         pThis->OnEvent(&event);
  1945.         if (event.m_hResult != S_OK)
  1946.             return event.m_hResult;
  1947.     }
  1948.  
  1949.     // Currently we only support Optimistic binding ala VB4
  1950.     // In this model, requests always succeed
  1951.     return S_OK;
  1952. }
  1953.  
  1954. /////////////////////////////////////////////////////////////////////////////
  1955. // COleControlSite::XEventSink
  1956.  
  1957. STDMETHODIMP_(ULONG) COleControlSite::XEventSink::AddRef()
  1958. {
  1959.     return 1;
  1960. }
  1961.  
  1962. STDMETHODIMP_(ULONG) COleControlSite::XEventSink::Release()
  1963. {
  1964.     return 0;
  1965. }
  1966.  
  1967. STDMETHODIMP COleControlSite::XEventSink::QueryInterface(
  1968.     REFIID iid, LPVOID* ppvObj)
  1969. {
  1970.     METHOD_PROLOGUE_EX_(COleControlSite, EventSink)
  1971.  
  1972.     if (IsEqualIID(iid, IID_IUnknown) ||
  1973.         IsEqualIID(iid, IID_IDispatch) ||
  1974.         IsEqualIID(iid, pThis->m_iidEvents))
  1975.     {
  1976.         *ppvObj = this;
  1977.         AddRef();
  1978.         return S_OK;
  1979.     }
  1980.     else
  1981.     {
  1982.         return E_NOINTERFACE;
  1983.     }
  1984. }
  1985.  
  1986. STDMETHODIMP COleControlSite::XEventSink::GetTypeInfoCount(
  1987.     unsigned int*)
  1988. {
  1989.     return E_NOTIMPL;
  1990. }
  1991.  
  1992. STDMETHODIMP COleControlSite::XEventSink::GetTypeInfo(
  1993.     unsigned int, LCID, ITypeInfo**)
  1994. {
  1995.     return E_NOTIMPL;
  1996. }
  1997.  
  1998. STDMETHODIMP COleControlSite::XEventSink::GetIDsOfNames(
  1999.     REFIID, LPOLESTR*, unsigned int, LCID, DISPID*)
  2000. {
  2001.     return E_NOTIMPL;
  2002. }
  2003.  
  2004. STDMETHODIMP COleControlSite::XEventSink::Invoke(
  2005.     DISPID dispid, REFIID, LCID, unsigned short wFlags,
  2006.     DISPPARAMS* pDispParams, VARIANT* pvarResult,
  2007.     EXCEPINFO* pExcepInfo, unsigned int* puArgError)
  2008. {
  2009.     UNUSED(wFlags);
  2010.  
  2011.     METHOD_PROLOGUE_EX(COleControlSite, EventSink)
  2012.     ASSERT(pThis->m_pCtrlCont != NULL);
  2013.     ASSERT(pThis->m_pCtrlCont->m_pWnd != NULL);
  2014.     ASSERT(wFlags == DISPATCH_METHOD);
  2015.  
  2016.     AFX_EVENT event(AFX_EVENT::event, dispid, pDispParams, pExcepInfo,
  2017.         puArgError);
  2018.  
  2019.     pThis->OnEvent(&event);
  2020.  
  2021.     if (pvarResult != NULL)
  2022.         ::VariantClear(pvarResult);
  2023.  
  2024.     return event.m_hResult;
  2025. }
  2026.  
  2027. #if !defined(_WIN32_WCE)
  2028. /////////////////////////////////////////////////////////////////////////////
  2029. // CDataSourceControl
  2030.  
  2031.  
  2032. CDataSourceControl::CDataSourceControl(COleControlSite *pClientSite) :
  2033.     m_pClientSite(pClientSite),
  2034.     m_pCursorMove(NULL),
  2035.     m_pCursorUpdateARow(NULL),
  2036.     m_pMetaRowData(NULL),
  2037.     m_pVarData(NULL),
  2038.     m_nColumns(0),
  2039.     m_nBindings(0),
  2040.     m_pColumnBindings(NULL),
  2041.     m_pValues(NULL),
  2042.     m_bUpdateInProgress(FALSE),
  2043.     m_pDataSource(NULL),
  2044.     m_pRowPosition(NULL),
  2045.     m_pRowset(NULL),
  2046.     m_pDynamicAccessor(NULL),
  2047.     m_dwRowsetNotify(0)
  2048. {
  2049.     ASSERT(pClientSite);
  2050. }
  2051.  
  2052. CDataSourceControl::~CDataSourceControl()
  2053. {
  2054.     // cancel ole/db notifications
  2055.     if (m_dwRowsetNotify != 0 && m_pRowset != NULL)
  2056.     {
  2057.         LPCONNECTIONPOINTCONTAINER pConnPtCont;
  2058.  
  2059.         if (SUCCEEDED(m_pRowset->m_spRowset->QueryInterface(IID_IConnectionPointContainer,
  2060.                 (LPVOID*)&pConnPtCont)))
  2061.         {
  2062.             ASSERT(pConnPtCont != NULL);
  2063.             LPCONNECTIONPOINT pConnPt = NULL;
  2064.  
  2065.             if (SUCCEEDED(pConnPtCont->FindConnectionPoint(IID_IRowsetNotify, &pConnPt)))
  2066.             {
  2067.                 ASSERT(pConnPt != NULL);
  2068.                 pConnPt->Unadvise(m_dwRowsetNotify);
  2069.                 pConnPt->Release();
  2070.             }
  2071.  
  2072.             pConnPtCont->Release();
  2073.         }
  2074.     }
  2075.  
  2076.     // Now go through all cursor bound properties
  2077.     while (!m_CursorBoundProps.IsEmpty())
  2078.     {
  2079.         CDataBoundProperty* pProp = (CDataBoundProperty*) m_CursorBoundProps.GetHead();
  2080.         pProp->m_pClientSite->BindProperty(pProp->m_dispid, NULL);
  2081.     }
  2082.     m_CursorBoundProps.RemoveAll();
  2083.  
  2084.     if (m_pValues)
  2085.     {
  2086.         for (int i=0; i<m_nBindings; i++)
  2087.             ::VariantClear(&m_pValues[i]);
  2088.         if (m_nBindings)
  2089.         {
  2090.             delete[] m_pColumnBindings;
  2091.             delete[] m_pValues;
  2092.         }
  2093.     }
  2094.  
  2095.     if (m_pCursorMove)
  2096.         m_pCursorMove->Release();
  2097.  
  2098.     if (m_pCursorUpdateARow)
  2099.         m_pCursorUpdateARow->Release();
  2100.  
  2101.     if (m_pMetaRowData)
  2102.     {
  2103.         for (int nCol=0; nCol<m_nColumns; nCol++)
  2104.         {
  2105.             m_pMetaRowData[nCol].m_pClientList->RemoveAll();
  2106.             delete m_pMetaRowData[nCol].m_pClientList;
  2107.         }
  2108.         ::CoTaskMemFree(m_pMetaRowData);
  2109.     }
  2110.  
  2111.     if (m_pVarData)
  2112.         ::CoTaskMemFree(m_pVarData);
  2113.  
  2114.     if(m_pDynamicAccessor != NULL)
  2115.     {
  2116.         m_pDynamicAccessor->ReleaseAccessors(m_pRowset->m_spRowset);
  2117.         m_pDynamicAccessor->Close();
  2118.     }
  2119.     delete m_pDynamicAccessor;
  2120.     delete m_pRowset;
  2121.     if (m_pRowPosition != NULL)
  2122.         m_pRowPosition->Release();
  2123.     if (m_pDataSource != NULL)
  2124.         m_pDataSource->Release();
  2125. }
  2126.  
  2127. interface IVBDSC : public IUnknown
  2128. {
  2129. public:
  2130.     virtual HRESULT STDMETHODCALLTYPE CancelUnload(BOOL __RPC_FAR* pfCancel) = 0;
  2131.     virtual HRESULT STDMETHODCALLTYPE Error(DWORD dwErr, BOOL __RPC_FAR* pfShowError) = 0;
  2132.     virtual HRESULT STDMETHODCALLTYPE CreateCursor(ICursor __RPC_FAR* __RPC_FAR* ppCursor) = 0;
  2133. };
  2134.  
  2135. const IID IID_IVBDSC = {0x1ab42240,0x8c70,0x11ce,{0x94,0x21,0x0,0xaa,0x0,0x62,0xbe,0x57}};
  2136. const IID CLSID_DataAdapter = {0x3A08E130L,0x8F65,0x11D0,{0x94,0x84,0x00,0xA0,0xC9,0x11,0x10,0xED}};
  2137.  
  2138. HRESULT CDataSourceControl::Initialize()
  2139. {
  2140.     // The following is a work around for RDC behaviour when on an invisible dlg
  2141.     // When the dlg is invisible it cannot display the ODBC connect dialog
  2142.     // So check if visible, if not make it so and move it to the center
  2143.     // of the screen with null size. Then do the connect dialog
  2144.     // Finally put it all back like it was.
  2145.     CWnd* pParent = m_pClientSite->m_pWndCtrl->GetTopLevelParent();
  2146.     BOOL bHidden = !pParent->IsWindowVisible();
  2147.     CRect rcParent;
  2148.     if (bHidden)
  2149.     {
  2150.         CRect rcDesktop;
  2151.         CWnd::GetDesktopWindow()->GetWindowRect(&rcDesktop);
  2152.         pParent->GetWindowRect(&rcParent);
  2153.         pParent->MoveWindow((rcDesktop.right - rcDesktop.left)/2, (rcDesktop.bottom - rcDesktop.top)/2, 0, 0, FALSE);
  2154.         pParent->ShowWindow(SW_SHOWNORMAL);
  2155.     }
  2156.     IVBDSC* pDSC;
  2157.     HRESULT hRes;
  2158.  
  2159.     hRes = m_pClientSite->m_pObject->QueryInterface(IID_IDataSource, (void**)&m_pDataSource);
  2160.     if (SUCCEEDED(hRes))
  2161.     {
  2162.         hRes = m_pDataSource->GetDataMember(NULL, &IID_IRowPosition, (IUnknown**)&m_pRowPosition);
  2163.         if (FAILED(hRes))
  2164.         {
  2165.             if (bHidden)
  2166.             {
  2167.                 pParent->MoveWindow(rcParent.left, rcParent.top, rcParent.right - rcParent.left, rcParent.bottom - rcParent.top, FALSE);
  2168.                 pParent->ShowWindow(SW_HIDE);
  2169.             }
  2170.             return hRes;
  2171.         }
  2172.     }
  2173.     else
  2174.     {
  2175.         hRes = m_pClientSite->m_pObject->QueryInterface(IID_IVBDSC, (void**)&pDSC);
  2176.         if (FAILED(hRes))
  2177.             return hRes;
  2178.         ICursor* pCursor;
  2179.         pDSC->CreateCursor(&pCursor);
  2180.         pDSC->Release();
  2181.         if (!pCursor)
  2182.             return E_FAIL;
  2183.  
  2184.         hRes = pCursor->QueryInterface(IID_ICursorMove,
  2185.             (LPVOID *)&m_pCursorMove);
  2186.  
  2187.         pCursor->Release();
  2188.  
  2189.         if (FAILED(hRes))
  2190.             return hRes;
  2191.  
  2192.         hRes = m_pCursorMove->QueryInterface(IID_ICursorUpdateARow,
  2193.             (LPVOID *)&m_pCursorUpdateARow);
  2194.     }
  2195.  
  2196.     hRes = GetMetaData();
  2197.  
  2198.     if (bHidden)
  2199.     {
  2200.         pParent->MoveWindow(rcParent.left, rcParent.top, rcParent.right - rcParent.left, rcParent.bottom - rcParent.top, FALSE);
  2201.         pParent->ShowWindow(SW_HIDE);
  2202.     }
  2203.  
  2204.     return hRes;
  2205. }
  2206.  
  2207. IUnknown* CDataSourceControl::GetCursor()
  2208. {
  2209.     ASSERT(m_pClientSite != NULL);
  2210.  
  2211.     if (m_pDataSource != NULL)
  2212.     {
  2213.         if(m_pRowset != NULL)
  2214.             return m_pDataSource;
  2215.         return NULL;
  2216.     }
  2217.  
  2218.     ICursor* pCursor;
  2219.     if (!m_pCursorMove)
  2220.     {
  2221.         IVBDSC* pDSC;
  2222.         HRESULT hRes;
  2223.         hRes = m_pClientSite->m_pObject->QueryInterface(IID_IVBDSC, (void**)&pDSC);
  2224.         if (FAILED(hRes))
  2225.             return NULL;
  2226.         pDSC->CreateCursor(&pCursor);
  2227.         pDSC->Release();
  2228.         if (!pCursor)
  2229.             return NULL;
  2230.         return pCursor;
  2231.     }
  2232.     if (SUCCEEDED(m_pCursorMove->QueryInterface(IID_ICursor, (LPVOID *) &pCursor)))
  2233.             return pCursor;
  2234.  
  2235.     ASSERT(FALSE); // DSC Cursor Not Found
  2236.     return NULL;
  2237. }
  2238.  
  2239. HRESULT CDataSourceControl::GetMetaData()
  2240. {
  2241.     HRESULT hRes;
  2242.     METAROWTYPE* pOldMetaData = m_pMetaRowData;
  2243.     int nOldColumns = m_nColumns;
  2244.  
  2245.     if (m_pDataSource != NULL)
  2246.     {
  2247.         IRowset* pRowset;
  2248.  
  2249.         hRes = m_pRowPosition->GetRowset(IID_IRowset, reinterpret_cast<IUnknown**>(&pRowset));
  2250.         if (FAILED(hRes))
  2251.             return hRes;
  2252.  
  2253.         {
  2254.             LPCONNECTIONPOINTCONTAINER pConnPtCont;
  2255.  
  2256.             if (SUCCEEDED(pRowset->QueryInterface(IID_IConnectionPointContainer,
  2257.                     (LPVOID*)&pConnPtCont)))
  2258.             {
  2259.                 ASSERT(pConnPtCont != NULL);
  2260.                 LPCONNECTIONPOINT pConnPt = NULL;
  2261.  
  2262.                 if (SUCCEEDED(pConnPtCont->FindConnectionPoint(IID_IRowsetNotify, &pConnPt)))
  2263.                 {
  2264.                     ASSERT(pConnPt != NULL);
  2265.                     pConnPt->Advise(&m_pClientSite->m_xRowsetNotify, &m_dwRowsetNotify);
  2266.                     pConnPt->Release();
  2267.                 }
  2268.  
  2269.                 pConnPtCont->Release();
  2270.             }
  2271.         }
  2272.  
  2273.         m_pRowset = new CRowset(pRowset);
  2274.         pRowset->Release();
  2275.         m_pRowset->SetupOptionalRowsetInterfaces();
  2276.         m_pDynamicAccessor = new CDynamicAccessor;
  2277.         m_pDynamicAccessor->BindColumns(m_pRowset->m_spRowset);
  2278.         m_pRowset->SetAccessor(m_pDynamicAccessor);
  2279.         m_nColumns = m_pDynamicAccessor->GetColumnCount();
  2280.         m_pMetaRowData = (METAROWTYPE*)::CoTaskMemAlloc(sizeof(METAROWTYPE) * m_nColumns);
  2281.         ASSERT(m_pMetaRowData);
  2282.         memset(m_pMetaRowData, 0, sizeof(METAROWTYPE) * m_nColumns);
  2283.         m_pRowset->MoveFirst();
  2284.         m_pRowset->ReleaseRows();
  2285.     }
  2286.     else
  2287.     {
  2288.         ULONG nRows;
  2289.         ICursor* pCursor = (LPCURSOR)m_pCursorMove;
  2290.         ICursor* pColumnCursor;
  2291.  
  2292.         if (pCursor == NULL)
  2293.             return S_OK;
  2294.  
  2295.         hRes = pCursor->GetColumnsCursor(IID_ICursor, (IUnknown **) &pColumnCursor, &nRows);
  2296.         if (FAILED(hRes))
  2297.             return hRes;
  2298.  
  2299.         DBCOLUMNBINDING MetaColumns[2];
  2300.         CopyColumnID(&MetaColumns[0].columnID, &COLUMN_COLUMNID);
  2301.         MetaColumns[0].obData = offsetof(METAROWTYPE, idColumnID);
  2302.         MetaColumns[0].cbMaxLen = DB_NOMAXLENGTH;
  2303.         MetaColumns[0].obInfo = offsetof(METAROWTYPE, dwColumnID);
  2304.         MetaColumns[0].obVarDataLen = DB_NOVALUE;
  2305.         MetaColumns[0].dwBinding = DBBINDING_DEFAULT;
  2306.         MetaColumns[0].dwDataType = DBTYPE_COLUMNID;
  2307.  
  2308.         CopyColumnID(&MetaColumns[1].columnID, &COLUMN_NAME);
  2309.         MetaColumns[1].obData = offsetof(METAROWTYPE, lpstrName);
  2310.         MetaColumns[1].cbMaxLen = DB_NOMAXLENGTH;
  2311.         MetaColumns[1].obInfo = offsetof(METAROWTYPE, dwName);
  2312.         MetaColumns[1].obVarDataLen = DB_NOVALUE;
  2313.         MetaColumns[1].dwBinding = DBBINDING_DEFAULT;
  2314.         MetaColumns[1].dwDataType = VT_LPSTR;
  2315.  
  2316.         hRes = pColumnCursor->SetBindings(2, MetaColumns, sizeof(METAROWTYPE),
  2317.             DBCOLUMNBINDOPTS_REPLACE);
  2318.         if (FAILED(hRes))
  2319.         {
  2320.             pColumnCursor->Release();
  2321.             return hRes;
  2322.         }
  2323.  
  2324.         DBFETCHROWS FetchRows;
  2325.         FetchRows.cRowsRequested = nRows;
  2326.         FetchRows.dwFlags = DBROWFETCH_CALLEEALLOCATES;
  2327.         FetchRows.pData = NULL;
  2328.         FetchRows.pVarData = NULL;
  2329.         FetchRows.cbVarData = 0;
  2330.  
  2331.         LARGE_INTEGER dlZero;
  2332.         LISet32(dlZero, 0);
  2333.         hRes = pColumnCursor->GetNextRows(dlZero, &FetchRows);
  2334.         if (FAILED(hRes))
  2335.         {
  2336.             pColumnCursor->Release();
  2337.             return hRes;
  2338.         }
  2339.  
  2340.         m_pMetaRowData = (METAROWTYPE *)FetchRows.pData;
  2341.         ASSERT(m_pMetaRowData);
  2342.         nRows = FetchRows.cRowsReturned;       // in case it changed
  2343.         m_pVarData = FetchRows.pVarData;
  2344.  
  2345.         m_nColumns = nRows;
  2346.  
  2347.         pColumnCursor->Release();
  2348.     }
  2349.  
  2350.     for (int nCol=0; nCol<m_nColumns; nCol++)
  2351.         m_pMetaRowData[nCol].m_pClientList = new CPtrList;
  2352.  
  2353.     // re-establish all bound property sites and then delete old meta-data
  2354.     if (pOldMetaData)
  2355.     {
  2356.         for (int nCol=0; nCol<nOldColumns; nCol++)
  2357.         {
  2358.             POSITION pos = pOldMetaData[nCol].m_pClientList->GetHeadPosition();
  2359.             while (pos)
  2360.             {
  2361.                 COleControlSite* pSite = (COleControlSite *)
  2362.                     m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
  2363.                 BindProp(pSite, TRUE);
  2364.             }
  2365.             pOldMetaData[nCol].m_pClientList->RemoveAll();
  2366.             delete pOldMetaData[nCol].m_pClientList;
  2367.         }
  2368.         ::CoTaskMemFree(pOldMetaData);
  2369.     }
  2370.  
  2371.     return hRes;
  2372. }
  2373.  
  2374. BOOL CDataSourceControl::CopyColumnID(
  2375.     DBCOLUMNID* pcidDst, DBCOLUMNID const *pcidSrc)
  2376. {
  2377.     pcidDst->dwKind = pcidSrc->dwKind;
  2378.  
  2379.     switch (pcidSrc->dwKind)
  2380.     {
  2381.     case DBCOLKIND_GUID_NUMBER:
  2382.         pcidDst->guid = pcidSrc->guid;
  2383.         pcidDst->lNumber = pcidSrc->lNumber;
  2384.         break;
  2385.     case DBCOLKIND_GUID_NAME:
  2386.         pcidDst->guid = pcidSrc->guid;
  2387.         // fall through
  2388.     case DBCOLKIND_NAME:
  2389.         pcidDst->lpdbsz = (LPDBSTR) ::CoTaskMemAlloc(sizeof(DBCHAR) * (ldbstrlen(pcidSrc->lpdbsz) + 1));
  2390.         if (!pcidDst->lpdbsz)
  2391.             return FALSE;
  2392.         ldbstrcpy(pcidDst->lpdbsz, pcidSrc->lpdbsz);
  2393.         break;
  2394.     }
  2395.     return TRUE;
  2396. }
  2397.  
  2398. // Make a bound control/bound property a consumer to a particular column in this DSC
  2399. void CDataSourceControl::BindProp(COleControlSite* pClientSite, BOOL bBind)
  2400. {
  2401.     ASSERT(pClientSite);
  2402.  
  2403.     if (bBind)
  2404.     {
  2405.         BindProp(pClientSite, FALSE);
  2406.         ASSERT(pClientSite->m_pDSCSite == m_pClientSite);
  2407.         if (m_pDataSource != NULL)
  2408.         {
  2409.             for (int nCol=0; nCol<m_nColumns; nCol++)
  2410.             {
  2411.                 if (pClientSite->m_strDataField == m_pDynamicAccessor->GetColumnName(nCol + 1))
  2412.                 {
  2413.                     m_pMetaRowData[nCol].m_pClientList->AddTail(pClientSite);
  2414.                     return;
  2415.                 }
  2416.             }
  2417.         }
  2418.         else
  2419.         {
  2420.             for (int nCol=0; nCol<m_nColumns; nCol++)
  2421.             {
  2422.                 if (m_pMetaRowData[nCol].lpstrName == NULL)
  2423.                     continue;
  2424.                 if (pClientSite->m_strDataField == m_pMetaRowData[nCol].lpstrName)
  2425.                 {
  2426.                     m_pMetaRowData[nCol].m_pClientList->AddTail(pClientSite);
  2427.                     return;
  2428.                 }
  2429.             }
  2430.         }
  2431.         return;
  2432.     }
  2433.     UpdateCursor();
  2434.     // UnBind
  2435.     for (int nCol=0; nCol<m_nColumns; nCol++)
  2436.     {
  2437.         POSITION pos = m_pMetaRowData[nCol].m_pClientList->GetHeadPosition();
  2438.         POSITION prev;
  2439.         while (pos)
  2440.         {
  2441.             prev = pos;
  2442.             COleControlSite* pSite = (COleControlSite *)
  2443.                 m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
  2444.             if (pSite == pClientSite)
  2445.             {
  2446.                 m_pMetaRowData[nCol].m_pClientList->RemoveAt(prev);
  2447.                 return;
  2448.             }
  2449.         }
  2450.     }
  2451. }
  2452.  
  2453. // Make a cursor bound control property a client to this control
  2454. void CDataSourceControl::BindProp(CDataBoundProperty* pProperty, BOOL bBind)
  2455. {
  2456.     ASSERT(pProperty);
  2457.  
  2458.     if (bBind)
  2459.     {
  2460.         BindProp(pProperty, FALSE);
  2461.         m_CursorBoundProps.AddTail(pProperty);
  2462.     }
  2463.     else
  2464.     {
  2465.         UpdateCursor();
  2466.         POSITION pos = m_CursorBoundProps.Find(pProperty);
  2467.         if (pos != NULL)
  2468.             m_CursorBoundProps.RemoveAt(pos);
  2469.     }
  2470. }
  2471.  
  2472. void CDataSourceControl::BindColumns()
  2473. {
  2474.     if (m_pDataSource != NULL)
  2475.     {
  2476.         // this is done automatically by CDynamicAccessor
  2477.         GetBoundClientRow();
  2478.         UpdateControls();
  2479.         return;
  2480.     }
  2481.     if (m_pValues)
  2482.     {
  2483.         for (int i=0; i<m_nBindings; i++)
  2484.             ::VariantClear(&m_pValues[i]);
  2485.         if (m_nBindings > 0)
  2486.         {
  2487.             delete[] m_pValues;
  2488.             delete[] m_pColumnBindings;
  2489.         }
  2490.         m_pValues = NULL;
  2491.     }
  2492.     m_nBindings = 0;
  2493.     for (int nCol=0; nCol<m_nColumns; nCol++)
  2494.     {
  2495.         m_nBindings += m_pMetaRowData[nCol].m_pClientList->GetCount();
  2496.     }
  2497.     if (m_nBindings > 0)
  2498.         m_pColumnBindings = new DBCOLUMNBINDING[m_nBindings];
  2499.     int nItem = 0;
  2500.     for (nCol=0; nCol<m_nColumns; nCol++)
  2501.     {
  2502.         POSITION pos = m_pMetaRowData[nCol].m_pClientList->GetHeadPosition();
  2503.         while (pos)
  2504.         {
  2505.             COleControlSite* pSite = (COleControlSite *)
  2506.                 m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
  2507.             CopyColumnID(&m_pColumnBindings[nItem].columnID, &m_pMetaRowData[nCol].idColumnID);
  2508.             m_pColumnBindings[nItem].obData = sizeof(VARIANT) * nItem;
  2509.             m_pColumnBindings[nItem].cbMaxLen = DB_NOMAXLENGTH;
  2510.             m_pColumnBindings[nItem].obInfo = DB_NOVALUE;
  2511.             m_pColumnBindings[nItem].obVarDataLen = DB_NOVALUE;
  2512.             m_pColumnBindings[nItem].dwBinding = DBBINDING_VARIANT;
  2513.             m_pColumnBindings[nItem].dwDataType = pSite->m_dwType;
  2514.             nItem++;
  2515.         }
  2516.     }
  2517.     m_pCursorMove->SetBindings(m_nBindings, m_pColumnBindings,
  2518.         sizeof(VARIANT) * m_nBindings, DBCOLUMNBINDOPTS_REPLACE);
  2519.  
  2520.     if (m_nBindings)
  2521.         m_pValues = new VARIANT[m_nBindings];
  2522.  
  2523.     for (int i=0; i<m_nBindings; i++)
  2524.     {
  2525.         memset(&m_pValues[i], 0, sizeof(VARIANT));
  2526.         m_pValues[i].vt = VT_EMPTY;
  2527.     }
  2528.  
  2529.     GetBoundClientRow();
  2530.     UpdateControls();
  2531. }
  2532.  
  2533. HRESULT CDataSourceControl::GetBoundClientRow()
  2534. {
  2535.     DBFETCHROWS FetchRows;
  2536.  
  2537.     if (m_pDataSource != NULL)
  2538.     {
  2539.         if(m_pRowset == NULL)
  2540.             return S_OK;
  2541.  
  2542.         if(m_pRowset->m_hRow == NULL)
  2543.             return S_OK;
  2544.  
  2545.         return m_pRowset->GetData();
  2546.     }
  2547.  
  2548.     if (m_nBindings == 0)
  2549.         return S_OK;
  2550.  
  2551.     FetchRows.pData = m_pValues;
  2552.     FetchRows.pVarData = NULL;
  2553.     FetchRows.cbVarData = NULL;
  2554.     FetchRows.cRowsRequested = 1;
  2555.     FetchRows.dwFlags = 0;
  2556.  
  2557.     LARGE_INTEGER dl = { 0, 0};
  2558.  
  2559.     return m_pCursorMove->Move(1, (LPVOID)&DBBMK_CURRENT, dl, &FetchRows);
  2560. }
  2561.  
  2562. COleVariant CDataSourceControl::ToVariant(int nCol)
  2563. {
  2564.     ASSERT(m_pDataSource != NULL);
  2565.     ASSERT(m_pDynamicAccessor != NULL);
  2566.     COleVariant vt;
  2567.     DBSTATUS dbStatus;
  2568.     DBTYPE dbType;
  2569.  
  2570.     m_pDynamicAccessor->GetStatus(nCol, &dbStatus);
  2571.     if(dbStatus == DBSTATUS_S_ISNULL)
  2572.         return vt;                      // just return a blank variant
  2573.  
  2574.     if(!m_pDynamicAccessor->GetColumnType(nCol, &dbType))
  2575.         return vt;
  2576.     switch (dbType)
  2577.     {
  2578.     case DBTYPE_VARIANT:
  2579.         vt = COleVariant((LPCVARIANT)m_pDynamicAccessor->GetValue(nCol));
  2580.         break;
  2581.     case DBTYPE_STR:
  2582.         vt = COleVariant(CString((LPCSTR)m_pDynamicAccessor->GetValue(nCol)), VT_BSTR);
  2583.         break;
  2584.     case DBTYPE_WSTR:
  2585.     case DBTYPE_BSTR:
  2586.         vt = COleVariant(CString((LPCWSTR)m_pDynamicAccessor->GetValue(nCol)), VT_BSTR);
  2587.         break;
  2588.     case DBTYPE_I1:
  2589.     case DBTYPE_UI1:
  2590.         vt = COleVariant(*((BYTE*)m_pDynamicAccessor->GetValue(nCol)));
  2591.         break;
  2592.     case DBTYPE_I2:
  2593.     case DBTYPE_UI2:
  2594.         vt = COleVariant(*((short*)m_pDynamicAccessor->GetValue(nCol)));
  2595.         break;
  2596.     case DBTYPE_I4:
  2597.     case DBTYPE_UI4:
  2598.         vt = COleVariant(*((long*)m_pDynamicAccessor->GetValue(nCol)));
  2599.         break;
  2600.     case DBTYPE_R4:
  2601.         vt = COleVariant(*((float*)m_pDynamicAccessor->GetValue(nCol)));
  2602.         break;
  2603.     case DBTYPE_R8:
  2604.         vt = COleVariant(*((double*)m_pDynamicAccessor->GetValue(nCol)));
  2605.         break;
  2606.     case DBTYPE_BOOL:
  2607.         vt = COleVariant((short)*(BOOL*)m_pDynamicAccessor->GetValue(nCol), VT_BOOL);
  2608.         break;
  2609.     case DBTYPE_DATE:
  2610.         {
  2611.             COleDateTime dt(*((DATE*)m_pDynamicAccessor->GetValue(nCol)));
  2612.             vt = COleVariant(dt);
  2613.         }
  2614.         break;
  2615.     case DBTYPE_CY:
  2616.         {
  2617.             COleCurrency cy(*((CURRENCY*)m_pDynamicAccessor->GetValue(nCol)));
  2618.             vt = COleVariant(cy);
  2619.         }
  2620.         break;
  2621.     case DBTYPE_NUMERIC:
  2622.         {
  2623.             DB_NUMERIC num;
  2624.  
  2625.             if(m_pDynamicAccessor->GetValue(nCol, &num))
  2626.             {
  2627.                 double dbl;
  2628.  
  2629.                 dbl = (double)*((__int64*)num.val);
  2630.                 while(num.scale-- > 0)
  2631.                     dbl /= 10;
  2632.                 if(num.sign == 0)
  2633.                     dbl = -dbl;
  2634.                 vt = COleVariant(dbl);
  2635.             }
  2636.         }
  2637.         break;
  2638.     case DBTYPE_DBDATE:
  2639.         {
  2640.             DBDATE dbDate;
  2641.  
  2642.             if(m_pDynamicAccessor->GetValue(nCol, &dbDate))
  2643.             {
  2644.                 COleDateTime dt;
  2645.  
  2646.                 dt.SetDate(dbDate.year, dbDate.month, dbDate.day);
  2647.                 vt = COleVariant(dt);
  2648.             }
  2649.         }
  2650.         break;
  2651.     case DBTYPE_DBTIME:
  2652.         {
  2653.             DBTIME dbTime;
  2654.  
  2655.             if(m_pDynamicAccessor->GetValue(nCol, &dbTime))
  2656.             {
  2657.                 COleDateTime dt;
  2658.  
  2659.                 dt.SetTime(dbTime.hour, dbTime.minute, dbTime.second);
  2660.                 vt = COleVariant(dt);
  2661.             }
  2662.         }
  2663.         break;
  2664.     case DBTYPE_DBTIMESTAMP:
  2665.         {
  2666.             DBTIMESTAMP dbTimeStamp;
  2667.  
  2668.             if(m_pDynamicAccessor->GetValue(nCol, &dbTimeStamp))
  2669.             {
  2670.                 vt = COleVariant(COleDateTime(dbTimeStamp.year, dbTimeStamp.month, dbTimeStamp.day,
  2671.                                               dbTimeStamp.hour, dbTimeStamp.minute, dbTimeStamp.second));
  2672.             }
  2673.         }
  2674.         break;
  2675.     case DBTYPE_NULL:
  2676.     case DBTYPE_EMPTY:
  2677.         break;
  2678.     default:
  2679.         TRACE2("Unsupported DBTYPE (%d) in column %d\n", dbType, nCol);
  2680.         break;
  2681.     }
  2682.     return vt;
  2683. }
  2684.  
  2685. HRESULT CDataSourceControl::UpdateControls()
  2686. {
  2687.     m_bUpdateInProgress = TRUE;
  2688.     int nItem = 0;
  2689.     for (int nCol=0; nCol<m_nColumns; nCol++)
  2690.     {
  2691.         POSITION pos = m_pMetaRowData[nCol].m_pClientList->GetHeadPosition();
  2692.         while (pos)
  2693.         {
  2694.             COleControlSite* pSite = (COleControlSite *)
  2695.                 m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
  2696.  
  2697.             DISPPARAMS dispparamsSetProp;
  2698.             DISPID dispidNamed = DISPID_PROPERTYPUT;
  2699.             EXCEPINFO excepinfo;
  2700.             memset(&excepinfo, 0, sizeof(EXCEPINFO));
  2701.             UINT uArgErr;
  2702.             COleVariant vt;
  2703.             if (m_pDataSource != NULL)
  2704.             {
  2705.                 vt = ToVariant(nCol + 1);
  2706.                 dispparamsSetProp.rgvarg = &vt;
  2707.             }
  2708.             else
  2709.             {
  2710.                 dispparamsSetProp.rgvarg = &m_pValues[nItem];
  2711.             }
  2712.             dispparamsSetProp.rgdispidNamedArgs = &dispidNamed;
  2713.             dispparamsSetProp.cArgs = 1;
  2714.             dispparamsSetProp.cNamedArgs = 1;
  2715.             HRESULT hRes;
  2716.             LPDISPATCH pDispatch;
  2717.             pSite->m_bIgnoreNotify = TRUE;
  2718.             if (pSite->m_pObject == NULL)
  2719.                 continue;
  2720.             hRes = pSite->m_pObject->QueryInterface(IID_IDispatch, (LPVOID *) &pDispatch);
  2721.             if (FAILED(hRes))
  2722.                 continue;
  2723.             hRes = pDispatch->Invoke(pSite->m_defdispid, IID_NULL, 0, INVOKE_PROPERTYPUT, &dispparamsSetProp,
  2724.                 NULL, &excepinfo, &uArgErr);    //Set the bound control property
  2725.             pDispatch->Release();
  2726.             pSite->m_bIgnoreNotify = FALSE;
  2727.  
  2728.             if (excepinfo.bstrSource)
  2729.                 SysFreeString(excepinfo.bstrSource);
  2730.             if (excepinfo.bstrDescription)
  2731.                 SysFreeString(excepinfo.bstrDescription);
  2732.             if (excepinfo.bstrHelpFile)
  2733.                 SysFreeString(excepinfo.bstrHelpFile);
  2734.  
  2735.             vt.Clear();
  2736.             nItem++;
  2737.         }
  2738.     }
  2739.     m_bUpdateInProgress = FALSE;
  2740.     return S_OK;
  2741. }
  2742.  
  2743. HRESULT CDataSourceControl::UpdateCursor()
  2744. {
  2745.     HRESULT hRes;
  2746.     int nVariant = 0;
  2747.     int nDirtyField = 0;
  2748.  
  2749.     if (m_pDataSource != NULL)
  2750.     {
  2751.         if(m_pDynamicAccessor == NULL)
  2752.             return S_OK;
  2753.         // First go through all simple bound properties
  2754.         for (int nCol=1; nCol<=m_nColumns; nCol++)
  2755.         {
  2756.             POSITION pos = m_pMetaRowData[nCol - 1].m_pClientList->GetHeadPosition();
  2757.             while (pos)
  2758.             {
  2759.                 COleControlSite* pSite = (COleControlSite *)
  2760.                     m_pMetaRowData[nCol - 1].m_pClientList->GetNext(pos);
  2761.                 DBTYPE dbType;
  2762.  
  2763.                 if (pSite->m_bIsDirty)
  2764.                 {
  2765.                     pSite->m_bIsDirty = FALSE;
  2766.  
  2767.                     nDirtyField++;
  2768.                     if (nDirtyField == 1)
  2769.                     {
  2770.                         // UpdateinProgress semaphore - unexpected state
  2771.                         ASSERT(!m_bUpdateInProgress);
  2772.                         m_bUpdateInProgress = TRUE;
  2773.                     }
  2774.  
  2775.                     COleVariant var(pSite->m_varResult);
  2776.                     CManualAccessor accessor;
  2777.  
  2778.                     // Create accessor for output column
  2779.                     accessor.CreateAccessor(1, m_pDynamicAccessor->GetValue(nCol), m_pDynamicAccessor->m_pColumnInfo[nCol].ulColumnSize);
  2780.                     accessor.AddBindEntry(m_pDynamicAccessor->m_pColumnInfo[nCol].iOrdinal,
  2781.                                           m_pDynamicAccessor->m_pColumnInfo[nCol].wType,
  2782.                                           m_pDynamicAccessor->m_pColumnInfo[nCol].ulColumnSize,
  2783.                                           m_pDynamicAccessor->GetValue(nCol));
  2784.                     accessor.BindColumns(m_pRowset->m_spRowset);
  2785.  
  2786.                     VERIFY(m_pDynamicAccessor->GetColumnType(nCol, &dbType));
  2787.                     switch(dbType)
  2788.                     {
  2789.                     case DBTYPE_I2:
  2790.                         var.ChangeType(VT_I2);
  2791.                         m_pDynamicAccessor->SetValue(nCol, var.iVal);
  2792.                         break;
  2793.                     case DBTYPE_I4:
  2794.                         var.ChangeType(VT_I4);
  2795.                         m_pDynamicAccessor->SetValue(nCol, var.lVal);
  2796.                         break;
  2797.                     case DBTYPE_R4:
  2798.                         var.ChangeType(VT_R4);
  2799.                         m_pDynamicAccessor->SetValue(nCol, var.fltVal);
  2800.                         break;
  2801.                     case DBTYPE_R8:
  2802.                         var.ChangeType(VT_R8);
  2803.                         m_pDynamicAccessor->SetValue(nCol, var.dblVal);
  2804.                         break;
  2805.                     case DBTYPE_CY:
  2806.                         var.ChangeType(VT_CY);
  2807.                         *(CY*)m_pDynamicAccessor->GetValue(nCol) = var.cyVal;
  2808.                         break;
  2809.                     case DBTYPE_DATE:
  2810.                         var.ChangeType(VT_DATE);
  2811.                         m_pDynamicAccessor->SetValue(nCol, var.date);
  2812.                         break;
  2813.                     case DBTYPE_BSTR:
  2814.                     case DBTYPE_WSTR:
  2815.                         var.ChangeType(VT_BSTR);
  2816.                         wcsncpy((wchar_t*)m_pDynamicAccessor->GetValue(nCol), var.bstrVal, m_pDynamicAccessor->m_pColumnInfo[nCol].ulColumnSize);
  2817.                         break;
  2818.                     case DBTYPE_BOOL:
  2819.                         var.ChangeType(VT_BOOL);
  2820.                         m_pDynamicAccessor->SetValue(nCol, var.boolVal);
  2821.                         break;
  2822.                     case DBTYPE_DECIMAL:
  2823.                         var.ChangeType(VT_DECIMAL);
  2824.                         m_pDynamicAccessor->SetValue(nCol, var.decVal);
  2825.                         break;
  2826.                     case DBTYPE_UI1:
  2827.                         var.ChangeType(VT_UI1);
  2828.                         m_pDynamicAccessor->SetValue(nCol, var.bVal);
  2829.                         break;
  2830.                     case DBTYPE_I1:
  2831.                         var.ChangeType(VT_I1);
  2832.                         m_pDynamicAccessor->SetValue(nCol, (signed char)var.cVal);
  2833.                         break;
  2834.                     case DBTYPE_UI2:
  2835.                         var.ChangeType(VT_UI2);
  2836.                         m_pDynamicAccessor->SetValue(nCol, var.uiVal);
  2837.                         break;
  2838.                     case DBTYPE_UI4:
  2839.                         var.ChangeType(VT_UI4);
  2840.                         m_pDynamicAccessor->SetValue(nCol, var.ulVal);
  2841.                         break;
  2842.                     case DBTYPE_STR:
  2843.                         var.ChangeType(VT_BSTR);
  2844.                         WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, (char*)m_pDynamicAccessor->GetValue(nCol),
  2845.                                             m_pDynamicAccessor->m_pColumnInfo[nCol].ulColumnSize, NULL, NULL);
  2846.                         break;
  2847.                     default:
  2848.                         TRACE2("Unsupported DBTYPE (%d) in column %d\n", dbType, nCol);
  2849.                         break;
  2850.                     }
  2851.  
  2852.                     m_pRowset->SetAccessor(&accessor);
  2853.                     m_pRowset->SetData();
  2854.                     m_pRowset->SetAccessor(m_pDynamicAccessor);
  2855.  
  2856.                     ::VariantClear(&pSite->m_varResult);
  2857.                 }
  2858.                 nVariant++;
  2859.             }
  2860.         }
  2861.         if (nDirtyField > 0)
  2862.         {
  2863.             m_bUpdateInProgress = FALSE;
  2864.         }
  2865.         return S_OK;
  2866.     }
  2867.     // Do we have an updateable cursor?
  2868.     if (m_pCursorUpdateARow == NULL)
  2869.     {
  2870.         // If not attempt to get one
  2871.         hRes = m_pCursorMove->QueryInterface(IID_ICursorUpdateARow,
  2872.             (LPVOID *)&m_pCursorUpdateARow);
  2873.  
  2874.         if (FAILED(hRes))
  2875.             return S_OK; // no update cursor, so forget updating
  2876.     }
  2877.  
  2878.     // First go through all simple bound properties
  2879.     for (int nCol=0; nCol<m_nColumns; nCol++)
  2880.     {
  2881.         POSITION pos = m_pMetaRowData[nCol].m_pClientList->GetHeadPosition();
  2882.         while (pos)
  2883.         {
  2884.             COleControlSite* pSite = (COleControlSite *)
  2885.                 m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
  2886.  
  2887.             if (pSite->m_bIsDirty)
  2888.             {
  2889.                 pSite->m_bIsDirty = FALSE;
  2890.  
  2891.                 nDirtyField++;
  2892.                 if (nDirtyField == 1)
  2893.                 {
  2894.                     DWORD dwEdit;
  2895.                     hRes = m_pCursorUpdateARow->GetEditMode(&dwEdit);
  2896.                     if (FAILED(hRes))
  2897.                         return hRes;
  2898.                     if (dwEdit == DBEDITMODE_NONE)
  2899.                     {
  2900.                         hRes = m_pCursorUpdateARow->BeginUpdate(DBROWACTION_UPDATE);
  2901.                         if (FAILED(hRes))
  2902.                             return hRes;
  2903.                     }
  2904.                     // UpdateinProgress semaphore - unexpected state
  2905.                     ASSERT(!m_bUpdateInProgress);
  2906.                     m_bUpdateInProgress = TRUE;
  2907.                 }
  2908.                 DBBINDPARAMS bpBindParams;
  2909.                 DWORD dwIndicator = sizeof(VARIANT);
  2910.                 COleVariant vt;
  2911.                 switch (V_VT(&pSite->m_varResult))
  2912.                 {
  2913.                 case VT_EMPTY:
  2914.                 case VT_NULL:
  2915.                 case VT_ERROR:
  2916.                     dwIndicator = DB_NULL;
  2917.                     vt = pSite->m_varResult;
  2918.                     break;
  2919.                 case VT_BSTR:
  2920.                     if(*pSite->m_varResult.bstrVal == 0)
  2921.                     {
  2922.                         dwIndicator = DB_NULL;
  2923.                         break;
  2924.                     }
  2925.                 default:
  2926.                     vt = pSite->m_varResult;
  2927.                     break;
  2928.                 }
  2929.                 bpBindParams.cbMaxLen     = 0L;
  2930.                 bpBindParams.dwBinding    = DBBINDING_VARIANT;
  2931.                 bpBindParams.dwDataType   = m_pColumnBindings[nVariant].dwDataType;
  2932.                 bpBindParams.cbVarDataLen = 0L;
  2933.                 bpBindParams.dwInfo       = dwIndicator;
  2934.                 bpBindParams.pData        = &vt;
  2935.  
  2936.                 hRes = m_pCursorUpdateARow->SetColumn(&m_pColumnBindings[nVariant].columnID, &bpBindParams);
  2937.  
  2938.                 ::VariantClear(&pSite->m_varResult);
  2939.             }
  2940.             nVariant++;
  2941.         }
  2942.     }
  2943.     // Now go through all cursor bound properties
  2944.     POSITION pos = m_CursorBoundProps.GetHeadPosition();
  2945.     while (pos != NULL)
  2946.     {
  2947.         CDataBoundProperty* pProp = (CDataBoundProperty*) m_CursorBoundProps.GetNext(pos);
  2948.         if (pProp->m_pClientSite->m_pObject == NULL)
  2949.             continue;
  2950.         IBoundObject *pBO;
  2951.         if (SUCCEEDED(pProp->m_pClientSite->m_pObject->QueryInterface(IID_IBoundObject,
  2952.             (LPVOID *) &pBO)))
  2953.         {
  2954.             if (pBO->IsDirty(pProp->m_dispid) == S_OK)
  2955.             {
  2956.                 nDirtyField++;
  2957.                 if (nDirtyField == 1)
  2958.                 {
  2959.                     DWORD dwEdit;
  2960.                     hRes = m_pCursorUpdateARow->GetEditMode(&dwEdit);
  2961.                     if (FAILED(hRes))
  2962.                         return hRes;
  2963.                     if (dwEdit == DBEDITMODE_NONE)
  2964.                     {
  2965.                         hRes = m_pCursorUpdateARow->BeginUpdate(DBROWACTION_UPDATE);
  2966.                         if (FAILED(hRes))
  2967.                             return hRes;
  2968.                     }
  2969.                     // UpdateinProgress semaphore - unexpected state
  2970.                     ASSERT(!m_bUpdateInProgress);
  2971.                     m_bUpdateInProgress = TRUE;
  2972.                 }
  2973.             }
  2974.             pBO->Release();
  2975.         }
  2976.     }
  2977.  
  2978.     if (nDirtyField > 0)
  2979.     {
  2980.         hRes = m_pCursorUpdateARow->Update(0,0,0);
  2981.         m_bUpdateInProgress = FALSE;
  2982.         if (FAILED(hRes))
  2983.         {
  2984.             // Update failed w/dirty controls
  2985.             ASSERT(hRes!= S_OK);
  2986.             UpdateControls();
  2987.             return hRes;
  2988.         }
  2989.     }
  2990.  
  2991.     return S_OK;
  2992. }
  2993.  
  2994.  
  2995. /////////////////////////////////////////////////////////////////////////////
  2996. // CDataBoundProperty Handles Databound Controls
  2997.  
  2998. CDataBoundProperty::CDataBoundProperty(CDataBoundProperty* pLast, DISPID dispid, WORD ctlid) :
  2999.     m_dispid(dispid),
  3000.     m_ctlid(ctlid),
  3001.     m_pClientSite(NULL),
  3002.     m_pDSCSite(NULL),
  3003.     m_bIsDirty(FALSE),
  3004.     m_pNext(pLast)
  3005. {
  3006. }
  3007.  
  3008. void CDataBoundProperty::SetClientSite(COleControlSite *pClientSite)
  3009. {
  3010.     m_pClientSite = pClientSite;
  3011. }
  3012.  
  3013.  
  3014. // (Re)bind a cursor bound property to a DSC
  3015. void CDataBoundProperty::SetDSCSite(COleControlSite *pDSCSite)
  3016. {
  3017.     if (m_pDSCSite == pDSCSite)
  3018.         return;
  3019.     m_pDSCSite = pDSCSite;
  3020.     Notify();
  3021. }
  3022.  
  3023. CDataBoundProperty* CDataBoundProperty::GetNext()
  3024. {
  3025.     return m_pNext;
  3026. }
  3027.  
  3028. void CDataBoundProperty::RemoveSource()
  3029. {
  3030.     m_pDSCSite = NULL;
  3031.     Notify();
  3032. }
  3033.  
  3034. void CDataBoundProperty::Notify()
  3035. {
  3036.     if (m_dispid != DISPID_DATASOURCE)
  3037.     {
  3038.         IBoundObject *pBO;
  3039.         if (m_pClientSite != NULL)
  3040.         {
  3041.             if (SUCCEEDED(m_pClientSite->m_pObject->QueryInterface(IID_IBoundObject,
  3042.                 (LPVOID *) &pBO)))
  3043.             {
  3044.                 pBO->OnSourceChanged(m_dispid, m_pDSCSite != NULL, &m_bOwnXferOut);
  3045.                 pBO->Release();
  3046.             }
  3047.             else
  3048.             {
  3049.                 IUnknown* pUnk = GetCursor();
  3050.                 if (pUnk != NULL)
  3051.                 {
  3052.                     VARTYPE vt = VT_UNKNOWN;
  3053.                     if (m_pDSCSite->m_pDataSourceControl != NULL)
  3054.                         vt |= VT_MFCFORCEPUTREF;
  3055.                     m_pClientSite->SetProperty(m_dispid, vt, pUnk);
  3056.                 }
  3057.             }
  3058.         }
  3059.     }
  3060. }
  3061.  
  3062. IUnknown* CDataBoundProperty::GetCursor()
  3063. {
  3064.     if(m_pDSCSite == NULL)
  3065.         return NULL;
  3066.  
  3067.     m_pDSCSite->EnableDSC();
  3068.  
  3069.     ASSERT(m_pDSCSite->m_pDataSourceControl);
  3070.  
  3071.     m_pDSCSite->m_pDataSourceControl->BindProp(this);
  3072.  
  3073.     return m_pDSCSite->m_pDataSourceControl->GetCursor();
  3074. }
  3075. #endif // _WIN32_WCE
  3076.  
  3077. /////////////////////////////////////////////////////////////////////////////
  3078. // COleControlSite::XBoundObjectSite
  3079.  
  3080. HRESULT COleControlSite::GetCursor(
  3081.     DISPID dispid, LPUNKNOWN* ppcursorOut, LPVOID *ppcidOut)
  3082. {
  3083.     if (ppcidOut)
  3084.         *ppcidOut = NULL;
  3085.  
  3086. #if !defined(_WIN32_WCE)
  3087.     CDataBoundProperty* pBinding = m_pBindings;
  3088.     while (pBinding != NULL)
  3089.     {
  3090.         if (pBinding->m_dispid == dispid)
  3091.         {
  3092.             *ppcursorOut = pBinding->GetCursor();
  3093.             return S_OK;
  3094.         }
  3095.         pBinding = pBinding->GetNext();
  3096.     }
  3097. #endif // _WIN32_WCE
  3098.  
  3099.     return S_OK;
  3100. }
  3101.  
  3102. #if !defined(_WIN32_WCE)
  3103. STDMETHODIMP_(ULONG) COleControlSite::XBoundObjectSite::AddRef()
  3104. {
  3105.     METHOD_PROLOGUE_EX(COleControlSite, BoundObjectSite)
  3106.     return (ULONG)pThis->ExternalAddRef();
  3107. }
  3108.  
  3109. STDMETHODIMP_(ULONG) COleControlSite::XBoundObjectSite::Release()
  3110. {
  3111.     METHOD_PROLOGUE_EX(COleControlSite, BoundObjectSite)
  3112.     return (ULONG)pThis->ExternalRelease();
  3113. }
  3114.  
  3115. STDMETHODIMP COleControlSite::XBoundObjectSite::QueryInterface(
  3116.     REFIID iid, LPVOID far * ppvObj)
  3117. {
  3118.     METHOD_PROLOGUE_EX(COleControlSite, BoundObjectSite)
  3119.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  3120. }
  3121.  
  3122. STDMETHODIMP COleControlSite::XBoundObjectSite::GetCursor(
  3123.     DISPID dispid, LPLPCURSOR ppcursorOut, LPVOID *ppcidOut)
  3124. {
  3125.     METHOD_PROLOGUE_EX(COleControlSite, BoundObjectSite)
  3126.     return pThis->GetCursor(dispid, (LPUNKNOWN*)ppcursorOut, ppcidOut);
  3127. }
  3128.  
  3129.  
  3130. /////////////////////////////////////////////////////////////////////////////
  3131. // COleControlSite::XNotifyDBEvents
  3132.  
  3133. STDMETHODIMP_(ULONG) COleControlSite::XNotifyDBEvents::AddRef()
  3134. {
  3135.     return 1;
  3136. }
  3137.  
  3138. STDMETHODIMP_(ULONG) COleControlSite::XNotifyDBEvents::Release()
  3139. {
  3140.     return 0;
  3141. }
  3142.  
  3143. STDMETHODIMP COleControlSite::XNotifyDBEvents::QueryInterface(
  3144.     REFIID iid, LPVOID far * ppvObj)
  3145. {
  3146.     METHOD_PROLOGUE_EX_(COleControlSite, NotifyDBEvents)
  3147.  
  3148.     if (IsEqualIID(iid, IID_IUnknown) ||
  3149.         WCE_IF(FALSE, IsEqualIID(iid, IID_INotifyDBEvents)))
  3150.     {
  3151.         *ppvObj = this;
  3152.         AddRef();
  3153.         return S_OK;
  3154.     }
  3155.     else
  3156.     {
  3157.         return E_NOINTERFACE;
  3158.     }
  3159. }
  3160.  
  3161. STDMETHODIMP COleControlSite::XNotifyDBEvents::OKToDo(
  3162.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3163. {
  3164.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3165.  
  3166.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3167.         dscOKToDo);
  3168.     if (FAILED(hRes))
  3169.         return hRes;
  3170.  
  3171.     DWORD reason = rgReasons[0].dwReason;
  3172.  
  3173.     if (reason == DBREASON_SETCOLUMN ||
  3174.         reason == DBREASON_INSERTED ||
  3175.         reason == DBREASON_MODIFIED)
  3176.         return S_OK;
  3177.  
  3178.     // Mask out all notifications except as currency changes and update
  3179.     if (!(dwEventWhat & DBEVENT_CURRENT_ROW_CHANGED) &&
  3180.         reason != DBREASON_INSERTED &&
  3181.         reason != DBREASON_MODIFIED &&
  3182.         reason != DBREASON_DELETED &&
  3183.         reason != DBREASON_ADDNEW)
  3184.         return S_OK;
  3185.  
  3186.     CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3187.     if (pDSC == NULL)
  3188.         return S_OK;
  3189.  
  3190.     if (!(dwEventWhat & DBEVENT_CURRENT_ROW_CHANGED))
  3191.         return S_OK;
  3192.  
  3193.     return pDSC->UpdateCursor();
  3194. }
  3195.  
  3196. STDMETHODIMP COleControlSite::XNotifyDBEvents::Cancelled(
  3197.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3198. {
  3199.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3200.  
  3201.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3202.         dscCancelled);
  3203.     if (FAILED(hRes))
  3204.         return hRes;
  3205.  
  3206.     return S_OK;
  3207. }
  3208.  
  3209. STDMETHODIMP COleControlSite::XNotifyDBEvents::SyncBefore(
  3210.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3211. {
  3212.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3213.  
  3214.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3215.         dscSyncBefore);
  3216.     if (FAILED(hRes))
  3217.         return hRes;
  3218.  
  3219.     DWORD reason = rgReasons[0].dwReason;
  3220.  
  3221.     // Mask out all notifications except as shown
  3222.     if (reason != DBREASON_INSERTED &&
  3223.         reason != DBREASON_MODIFIED &&
  3224.         reason != DBREASON_ADDNEW)
  3225.         return S_OK;
  3226.  
  3227.     CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3228.     if (pDSC == NULL)
  3229.         return S_OK;
  3230.  
  3231.     if (dwEventWhat & DBEVENT_METADATA_CHANGED)
  3232.     {
  3233.         pDSC->UpdateCursor();
  3234.     }
  3235.  
  3236.     return S_OK;
  3237. }
  3238.  
  3239. STDMETHODIMP COleControlSite::XNotifyDBEvents::AboutToDo(
  3240.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3241. {
  3242.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3243.  
  3244.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3245.         dscAboutToDo);
  3246.     if (FAILED(hRes))
  3247.         return hRes;
  3248.  
  3249.     return S_OK;
  3250. }
  3251.  
  3252. STDMETHODIMP COleControlSite::XNotifyDBEvents::FailedToDo(
  3253.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3254. {
  3255.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3256.  
  3257.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3258.         dscFailedToDo);
  3259.     if (FAILED(hRes))
  3260.         return hRes;
  3261.  
  3262.     return S_OK;
  3263. }
  3264.  
  3265. STDMETHODIMP COleControlSite::XNotifyDBEvents::SyncAfter(
  3266.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3267. {
  3268.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3269.  
  3270.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3271.         dscSyncAfter);
  3272.     if (FAILED(hRes))
  3273.         return hRes;
  3274.  
  3275.     DWORD reason = rgReasons[0].dwReason;
  3276.  
  3277.     CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3278.     if (pDSC == NULL)
  3279.         return S_OK;
  3280.  
  3281.     //Check semaphore - don't want to collect data during Update if it was due to a Move (it's a NOP!)
  3282.     if (pDSC->m_bUpdateInProgress ||
  3283.         reason == DBREASON_EDIT ||
  3284.         reason == DBREASON_SETCOLUMN)
  3285.         return S_OK;
  3286.  
  3287.     //Mask out all notifications except as shown
  3288.     if (!(dwEventWhat & (DBEVENT_CURRENT_ROW_CHANGED | DBEVENT_CURRENT_ROW_DATA_CHANGED)))
  3289.         return S_OK;
  3290.  
  3291.     if (reason != DBREASON_INSERTED &&
  3292.         reason != DBREASON_MODIFIED)
  3293.     {
  3294.         BOOL bUpdateInProgress = pDSC->m_bUpdateInProgress;
  3295.         pDSC->m_bUpdateInProgress = TRUE;
  3296.         pDSC->GetBoundClientRow();
  3297.         pDSC->m_bUpdateInProgress = bUpdateInProgress;
  3298.         pDSC->UpdateControls();
  3299.     }
  3300.  
  3301.     return S_OK;
  3302. }
  3303.  
  3304. STDMETHODIMP COleControlSite::XNotifyDBEvents::DidEvent(
  3305.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[])
  3306. {
  3307.     METHOD_PROLOGUE_EX(COleControlSite, NotifyDBEvents)
  3308.  
  3309.     HRESULT hRes = FireEvent(dwEventWhat, cReasons, rgReasons,
  3310.         dscDidEvent);
  3311.     if (FAILED(hRes))
  3312.         return hRes;
  3313.  
  3314.     CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3315.     if (pDSC == NULL)
  3316.         return S_OK;
  3317.  
  3318.     if (dwEventWhat & DBEVENT_METADATA_CHANGED)
  3319.     {
  3320.         BOOL bUpdateInProgress = pDSC->m_bUpdateInProgress;
  3321.         pDSC->m_bUpdateInProgress = TRUE;
  3322.         pDSC->GetBoundClientRow();
  3323.         pDSC->m_bUpdateInProgress = bUpdateInProgress;
  3324.         pDSC->UpdateControls();
  3325.     }
  3326.  
  3327.     return S_OK;
  3328. }
  3329.  
  3330.  
  3331. HRESULT COleControlSite::XNotifyDBEvents::FireEvent(
  3332.     DWORD dwEventWhat, ULONG cReasons, DBNOTIFYREASON rgReasons[], DSCSTATE nState)
  3333. {
  3334.     METHOD_PROLOGUE_EX_(COleControlSite, NotifyDBEvents)
  3335.  
  3336.     if (dwEventWhat & DBEVENT_CURRENT_ROW_CHANGED
  3337.         || dwEventWhat & DBEVENT_CURRENT_ROW_DATA_CHANGED)
  3338.     {
  3339.         for (UINT i=0; i<cReasons; i++)
  3340.         {
  3341.             DSCREASON nReason = dscNoReason;
  3342.             switch (rgReasons[i].dwReason)
  3343.             {
  3344.             case DBREASON_CLOSE:
  3345.                 nReason = dscClose;
  3346.                 break;
  3347.             case DBREASON_FIND:
  3348.             case DBREASON_MOVE:
  3349.             case DBREASON_MOVEPERCENT:
  3350.             case DBREASON_NEWINDEX:
  3351.             case DBREASON_NEWPARAMETERS:
  3352.             case DBREASON_QUERYSPECCHANGED:
  3353.             case DBREASON_REFRESH:
  3354.             case DBREASON_SEEK:
  3355.             case DBREASON_SETRANGECHANGED:
  3356.                 nReason = dscMove;
  3357.                 break;
  3358.             case DBREASON_ADDNEW:
  3359.             case DBREASON_INSERTED:
  3360.                 nReason = dscInsert;
  3361.                 break;
  3362.             case DBREASON_EDIT:
  3363.                 nReason = dscEdit;
  3364.                 break;
  3365.             case DBREASON_MODIFIED:
  3366.             case DBREASON_RECALC:
  3367.             case DBREASON_ROLLBACK:
  3368.             case DBREASON_ROWFIXUP:
  3369.                 nReason = dscModify;
  3370.                 break;
  3371.             case DBREASON_DELETED:
  3372.                 nReason = dscDelete;
  3373.                 break;
  3374.             case DBREASON_COMMIT:
  3375.                 nReason = dscCommit;
  3376.                 break;
  3377.             }
  3378.             if (nReason != dscNoReason)
  3379.             {
  3380.                 AFX_EVENT event(AFX_EVENT::propDSCNotify);
  3381.                 event.m_nDSCState = nState;
  3382.                 event.m_nDSCReason = nReason;
  3383.                 pThis->OnEvent(&event);
  3384.                 return event.m_hResult;
  3385.             }
  3386.         }
  3387.         return S_OK;
  3388.     }
  3389.     return S_OK;
  3390. }
  3391.  
  3392. STDMETHODIMP_(ULONG) COleControlSite::XRowsetNotify::AddRef()
  3393. {
  3394.     return 1;
  3395. }
  3396.  
  3397. STDMETHODIMP_(ULONG) COleControlSite::XRowsetNotify::Release()
  3398. {
  3399.     return 0;
  3400. }
  3401.  
  3402. STDMETHODIMP COleControlSite::XRowsetNotify::QueryInterface(
  3403.     REFIID iid, LPVOID far * ppvObj)
  3404. {
  3405.     METHOD_PROLOGUE_EX_(COleControlSite, RowsetNotify)
  3406.  
  3407.     if (IsEqualIID(iid, IID_IUnknown) ||
  3408.         IsEqualIID(iid, IID_IRowsetNotify))
  3409.     {
  3410.         *ppvObj = this;
  3411.         AddRef();
  3412.         return S_OK;
  3413.     }
  3414.     return E_NOINTERFACE;
  3415. }
  3416.  
  3417. STDMETHODIMP COleControlSite::XRowsetNotify::OnFieldChange(
  3418.     IRowset* /*pRowset*/, HROW /*hRow*/, ULONG /*cColumns*/, ULONG /*rgColumns*/[],
  3419.     DBREASON /*eReason*/, DBEVENTPHASE ePhase, BOOL /*fCantDeny*/)
  3420. {
  3421.     METHOD_PROLOGUE_EX(COleControlSite, RowsetNotify)
  3422.  
  3423.     DSCSTATE nState = dscNoState;
  3424.     switch(ePhase)
  3425.     {
  3426.     case DBEVENTPHASE_OKTODO:
  3427.         nState = dscOKToDo;
  3428.         break;
  3429.     case DBEVENTPHASE_ABOUTTODO:
  3430.         nState = dscAboutToDo;
  3431.         break;
  3432.     case DBEVENTPHASE_SYNCHAFTER:
  3433.         nState = dscSyncAfter;
  3434.         break;
  3435.     case DBEVENTPHASE_FAILEDTODO:
  3436.         nState = dscFailedToDo;
  3437.         break;
  3438.     case DBEVENTPHASE_DIDEVENT:
  3439.         nState = dscDidEvent;
  3440.         break;
  3441.     }
  3442.     if(nState == dscDidEvent)
  3443.     {
  3444.         CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3445.         if (pDSC == NULL)
  3446.             return S_OK;
  3447.  
  3448.         if(pDSC->m_bUpdateInProgress == FALSE)
  3449.         {
  3450.             ASSERT(pDSC->m_pRowset);
  3451.  
  3452.             BOOL bUpdateInProgress = pDSC->m_bUpdateInProgress;
  3453.             pDSC->m_bUpdateInProgress = TRUE;
  3454.             pDSC->GetBoundClientRow();
  3455.             pDSC->m_bUpdateInProgress = bUpdateInProgress;
  3456.             pDSC->UpdateControls();
  3457.         }
  3458.     }
  3459.  
  3460.     AFX_EVENT event(AFX_EVENT::propDSCNotify);
  3461.     event.m_nDSCState = nState;
  3462.     event.m_nDSCReason = dscModify;
  3463.     pThis->OnEvent(&event);
  3464.     return event.m_hResult;
  3465. }
  3466.  
  3467. STDMETHODIMP COleControlSite::XRowsetNotify::OnRowChange(
  3468.     IRowset* /*pRowset*/, ULONG cRows, const HROW rghRows[],
  3469.     DBREASON eReason, DBEVENTPHASE ePhase, BOOL /*fCantDeny*/)
  3470. {
  3471.     METHOD_PROLOGUE_EX(COleControlSite, RowsetNotify)
  3472.  
  3473.     HRESULT hRes = S_OK;
  3474.  
  3475.     DSCSTATE nState = dscNoState;
  3476.     switch(ePhase)
  3477.     {
  3478.     case DBEVENTPHASE_OKTODO:
  3479.         nState = dscOKToDo;
  3480.         break;
  3481.     case DBEVENTPHASE_ABOUTTODO:
  3482.         nState = dscAboutToDo;
  3483.         break;
  3484.     case DBEVENTPHASE_SYNCHAFTER:
  3485.         nState = dscSyncAfter;
  3486.         break;
  3487.     case DBEVENTPHASE_FAILEDTODO:
  3488.         nState = dscFailedToDo;
  3489.         break;
  3490.     case DBEVENTPHASE_DIDEVENT:
  3491.         nState = dscDidEvent;
  3492.         break;
  3493.     }
  3494.     DSCREASON nReason = dscNoReason;
  3495.     switch(eReason)
  3496.     {
  3497.     case DBREASON_ROW_ACTIVATE:
  3498.         nReason = dscMove;
  3499.         break;
  3500.     case DBREASON_ROW_DELETE:
  3501.         nReason = dscDelete;
  3502.         break;
  3503.     case DBREASON_ROW_INSERT:
  3504.         nReason = dscInsert;
  3505.         break;
  3506.     case DBREASON_ROW_UPDATE:
  3507.         nReason = dscCommit;
  3508.         break;
  3509.     }
  3510.     CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3511.     if (pDSC == NULL)
  3512.         return S_OK;
  3513.  
  3514.     ASSERT(pDSC->m_pRowset);
  3515.  
  3516.     if (nReason == dscCommit && nState == dscAboutToDo)
  3517.     {
  3518.         pDSC->UpdateCursor();
  3519.     }
  3520.     else if ((nReason == dscMove && cRows == 1) || (nState == dscSyncAfter && nReason == dscInsert))
  3521.     {
  3522.         pDSC->UpdateCursor();
  3523.         pDSC->m_pRowset->m_hRow = rghRows[0];
  3524.  
  3525.         BOOL bUpdateInProgress = pDSC->m_bUpdateInProgress;
  3526.         pDSC->m_bUpdateInProgress = TRUE;
  3527.         pDSC->GetBoundClientRow();
  3528.         pDSC->m_bUpdateInProgress = bUpdateInProgress;
  3529.         if(!pDSC->m_bUpdateInProgress)
  3530.             pDSC->UpdateControls();
  3531.     }
  3532.     if (nReason != dscNoReason)
  3533.     {
  3534.         AFX_EVENT event(AFX_EVENT::propDSCNotify);
  3535.         event.m_nDSCState = nState;
  3536.         event.m_nDSCReason = nReason;
  3537.         pThis->OnEvent(&event);
  3538.         hRes = event.m_hResult;
  3539.         if(FAILED(hRes))
  3540.             return hRes;
  3541.     }
  3542.     return S_OK;
  3543. }
  3544.  
  3545. STDMETHODIMP COleControlSite::XRowsetNotify::OnRowsetChange(
  3546.     IRowset* /*pRowset*/, DBREASON eReason, DBEVENTPHASE /*ePhase*/, BOOL /*fCantDeny*/)
  3547. {
  3548.     METHOD_PROLOGUE_EX(COleControlSite, RowsetNotify)
  3549.  
  3550.     if(eReason == DBREASON_ROWSET_CHANGED)
  3551.     {
  3552.         CDataSourceControl* pDSC = pThis->m_pDataSourceControl;
  3553.         if (pDSC == NULL)
  3554.             return S_OK;
  3555.  
  3556.         ASSERT(pDSC->m_pRowset);
  3557.         ASSERT(pDSC->m_pDynamicAccessor);
  3558.  
  3559.         pDSC->m_pDynamicAccessor->ReleaseAccessors(pDSC->m_pRowset->m_spRowset);
  3560.         pDSC->m_pDynamicAccessor->Close();
  3561.         pDSC->m_pDynamicAccessor->BindColumns(pDSC->m_pRowset->m_spRowset);
  3562.         if( pDSC->m_nColumns != (int)pDSC->m_pDynamicAccessor->GetColumnCount() )
  3563.         {
  3564.             pDSC->m_nColumns = pDSC->m_pDynamicAccessor->GetColumnCount();
  3565.             ::CoTaskMemFree(pDSC->m_pMetaRowData);
  3566.             pDSC->m_pMetaRowData = (CDataSourceControl::METAROWTYPE*)::CoTaskMemAlloc(sizeof(CDataSourceControl::METAROWTYPE) * pDSC->m_nColumns);
  3567.             ASSERT(pDSC->m_pMetaRowData);
  3568.             memset(pDSC->m_pMetaRowData, 0, sizeof(CDataSourceControl::METAROWTYPE) * pDSC->m_nColumns);
  3569.         }
  3570.     }
  3571.  
  3572.     return S_OK;
  3573. }
  3574. #endif // _WIN32_WCE
  3575.